home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / smaltalk / manchest.lha / MANCHESTER / manchester / 4.1 / interactors / Interactors-Framework.st < prev    next >
Text File  |  1993-07-24  |  119KB  |  4,505 lines

  1. Controller subclass: #InteractorController
  2.     instanceVariableNames: ''
  3.     classVariableNames: ''
  4.     poolDictionaries: ''
  5.     category: 'Interactors-Framework'!
  6.  
  7.  
  8. !InteractorController methodsFor: 'control defaults'!
  9.  
  10. controlActivity
  11.  
  12.     sensor redButtonPressed ifTrue: [^view selectDown: sensor mousePoint].
  13.     sensor yellowButtonPressed ifTrue: [^view operateDown: sensor mousePoint].
  14.     sensor keyboardPressed ifTrue: [^view keyboardDown: sensor mousePoint].
  15.     ^view startUp: sensor mousePoint.    "Pseudo event, caught by controllers."! !
  16.  
  17. Object subclass: #Interactor
  18.     instanceVariableNames: 'clientData window selected extent sensor '
  19.     classVariableNames: ''
  20.     poolDictionaries: ''
  21.     category: 'Interactors-Framework'!
  22. Interactor comment:
  23. 'perspective            (Perspective) the perspective on which I am a representation
  24. dialogManager        (DialogManager) the dialog manager to which I am responsible
  25. operators            (Set of ?) the set of operators that I am willing to respond to
  26. selected            (Boolean) true if I am the destination for operations
  27. topRepresentation    (Representation) the root of the representation hierarchy of which I am part
  28. extent                (Point) my extent (including any decorations)
  29. bordered            (Boolean) true if I have a border around me
  30. identifier            (String/Symbol) the name with which I label myself during debugging
  31. window            (WindowRepresentation/ScheduledWindow?) the window on which I render myself'!
  32.  
  33.  
  34. !Interactor methodsFor: 'initialize-release'!
  35.  
  36. initialize
  37.     selected := false!
  38.  
  39. release
  40.  
  41.     window := sensor := nil.
  42.     super release.! !
  43.  
  44. !Interactor methodsFor: 'hierarchy'!
  45.  
  46. installComposites!
  47.  
  48. installHierarchy!
  49.  
  50. installSensor: aSensor
  51.  
  52.     self sensor: aSensor!
  53.  
  54. installWindow: aWindow
  55.  
  56.     self window: aWindow!
  57.  
  58. rootInteractor
  59.     ^self parent rootInteractor! !
  60.  
  61. !Interactor methodsFor: 'geometry'!
  62.  
  63. computeBounds: bounds
  64.     ^self subclassResponsibility!
  65.  
  66. computeExtent
  67.     ^self subclassResponsibility!
  68.  
  69. computeMinimumExtent
  70.     ^self computeExtent! !
  71.  
  72. !Interactor methodsFor: 'accessing'!
  73.  
  74. clientData
  75.     ^clientData!
  76.  
  77. clientData: aDatum
  78.     clientData := aDatum!
  79.  
  80. defaultExtent: ext
  81.     extent isNil ifTrue: [self extent: ext]!
  82.  
  83. extent
  84.     extent isNil ifTrue: [self extent: self minimumExtent].
  85.     ^extent copy!
  86.  
  87. extent: aPoint
  88.     extent := aPoint!
  89.  
  90. height
  91.     ^extent y!
  92.  
  93. height: h
  94.     ^extent y: h!
  95.  
  96. lookPreferences
  97.     ^self rootInteractor lookPreferences!
  98.  
  99. parent: p
  100.     "Catch any illicit attempts to install parents in interactors that have non (such
  101.     as the rootInteractor)"
  102.  
  103.     ^self shouldNotImplement!
  104.  
  105. selected
  106.     ^selected "isNil ifTrue: [selected := false] ifFalse: [selected]"!
  107.  
  108. selected: s
  109.     selected := s!
  110.  
  111. sensor
  112.     ^sensor!
  113.  
  114. sensor: s
  115.     sensor := s.
  116.     self window: s window!
  117.  
  118. transparentSelf!
  119.  
  120. width
  121.     ^extent x!
  122.  
  123. width: w
  124.     ^extent x: w!
  125.  
  126. window
  127.     ^window!
  128.  
  129. window: win
  130.     window := win! !
  131.  
  132. !Interactor methodsFor: 'rendering'!
  133.  
  134. damaged
  135.  
  136.     "An interactor that doesn't know how to handle damage should defer to its parent"
  137.  
  138.     ^self parent damaged!
  139.  
  140. graphicsContext
  141.     "An interactor that doesn't know about its graphics context should ask its parent for one."
  142.  
  143.     ^self parent graphicsContextFor: self!
  144.  
  145. graphicsContextFor: anInteractor
  146.     "An interactor that doesn't know about its graphics context should ask its parent for one."
  147.  
  148.     ^self parent graphicsContextFor: anInteractor!
  149.  
  150. render
  151.     ^self renderOn: self graphicsContext!
  152.  
  153. renderBackgroundOn: aGC
  154.  
  155.     aGC displayRectangle: self bounds!
  156.  
  157. renderDeselectedOn: aGC
  158.  
  159.     self
  160.         renderForeground: self foregroundColor
  161.         background: self backgroundColor
  162.         on: aGC!
  163.  
  164. renderForeground: foregroundColor background: backgroundColor on: aGC
  165.  
  166.     aGC paint: backgroundColor.
  167.     self renderBackgroundOn: aGC.
  168.     aGC paint: foregroundColor.
  169.     self renderForegroundOn: aGC!
  170.  
  171. renderForegroundOn: aGC!
  172.  
  173. renderGreyedOn: aGC
  174.  
  175.     self
  176.         renderForeground: self greyedForegroundColor
  177.         background: self greyedBackgroundColor
  178.         on: aGC!
  179.  
  180. renderOn: aGC
  181.     (aGC clippingBounds intersects: self bounds)
  182.         ifTrue:
  183.             [self selected isNil
  184.                 ifTrue:
  185.                     [self renderGreyedOn: aGC]
  186.                 ifFalse:
  187.                     [self selected
  188.                         ifTrue: [self renderSelectedOn: aGC]
  189.                         ifFalse: [self renderDeselectedOn: aGC]]]!
  190.  
  191. renderSelectedOn: aGC
  192.  
  193.     self
  194.         renderForeground: self selectionForegroundColor
  195.         background: self selectionBackgroundColor
  196.         on: aGC! !
  197.  
  198. !Interactor methodsFor: 'conversions'!
  199.  
  200. active
  201.     ^ActiveInteractor on: self!
  202.  
  203. bordered
  204.     ^BorderInteractor on: self!
  205.  
  206. bordered: n
  207.     ^self bordered borderWidth: n!
  208.  
  209. cachedScrolling
  210.     ^CachedScrollingInteractor on: self!
  211.  
  212. inset
  213.     ^InsetInteractor on: self!
  214.  
  215. inset: n
  216.     ^InsetInteractor inset: n on: self!
  217.  
  218. scrolling
  219.     ^ScrollingInteractor on: self! !
  220.  
  221. !Interactor methodsFor: 'visual properties'!
  222.  
  223. backgroundColor
  224.     ^self lookPreferences backgroundColor!
  225.  
  226. borderBackgroundColor
  227.  
  228.     ^ColorValue white!
  229.  
  230. borderBounds
  231.  
  232.     ^self origin corner: self corner - self cornerCorrection!
  233.  
  234. borderForegroundColor
  235.  
  236.     ^ColorValue black!
  237.  
  238. compositionBounds
  239.     | bb |
  240.     ^(bb := self borderBounds) origin + self borderWidth corner: bb corner!
  241.  
  242. cornerCorrection
  243.  
  244.     "Because the graphics system defines the bottom-right pixel of
  245.     an object to be one pixel in from the corner, we have to adjust
  246.     for the fact in certain conditions.  If this problem ever gets fixed,
  247.     this method will have to return 0@0 (no correction)."
  248.  
  249.     ^1@1!
  250.  
  251. foregroundColor
  252.     ^self lookPreferences foregroundColor!
  253.  
  254. greyedBackgroundColor
  255.     ^ColorValue brightness: 0.6!
  256.  
  257. greyedForegroundColor
  258.     ^ColorValue brightness: 0.8!
  259.  
  260. selectionBackgroundColor
  261.     ^self lookPreferences selectionBackgroundColor!
  262.  
  263. selectionForegroundColor
  264.     ^self lookPreferences selectionForegroundColor!
  265.  
  266. windowLabel: l
  267.     ^self rootInteractor windowLabel: l! !
  268.  
  269. !Interactor methodsFor: 'scheduling'!
  270.  
  271. close
  272.     self window isNil ifFalse: [self window controller close]!
  273.  
  274. open
  275.     ^(RootInteractor on: self) open! !
  276.  
  277. !Interactor methodsFor: 'event enquiry'!
  278.  
  279. containsPoint: aPoint
  280.     ^self bounds containsPoint: aPoint!
  281.  
  282. interactorAt: aPoint
  283.     "There's no point in checking further, it *MUST* be me!!!!!!"
  284.  
  285.     ^(self bounds containsPoint: aPoint) ifTrue: [self]! !
  286.  
  287. !Interactor methodsFor: 'event response'!
  288.  
  289. keyboardDown
  290.     "Throw away keyboard events that aren't intercepted lower down"
  291.  
  292.     [self sensor keyboardPressed]     whileTrue: [self sensor keyboardEvent]!
  293.  
  294. operateDown
  295.  
  296.     self inspect!
  297.  
  298. selectDown!
  299.  
  300. selectDownDown
  301.     ^self selectDown!
  302.  
  303. startUp
  304.  
  305.     "Author: IKP, 1992-08-22.   (This is all getting rather complicated.)"
  306.  
  307.     "This is a pseudo-event sent priodically for the benefit of Interactors
  308.     that encapsulate Smalltalk View-Controller pairs.  Legitimate Interactors
  309.     should ignore this event, since it does not signify any kind of I/O activity.
  310.     MVC-wrapping interactors should respond to this event by implementing
  311.     a control dispatch loop for the benefit of the underlying controller."! !
  312.  
  313. !Interactor methodsFor: 'default accessing'!
  314.  
  315. componentDeselected!
  316.  
  317. componentSelected!
  318.  
  319. isAlignedComposite
  320.     ^false!
  321.  
  322. isComposite
  323.     ^false!
  324.  
  325. isDynamicComposite
  326.     ^false!
  327.  
  328. radioGroup: aGrouper
  329.  
  330.     "Anything that doesn't override this basically doesn't care"! !
  331.  
  332. !Interactor methodsFor: 'error handling'!
  333.  
  334. uimsError
  335.     ^self error: 'degenerate case in UIMS geometry management - HELP!!!!!!'! !
  336.  
  337. !Interactor methodsFor: 'printing'!
  338.  
  339. auxiliaryPrintInfo
  340.     ^' (' , self minimumExtent printString , ' -> ' , self extent printString , ')'!
  341.  
  342. hierarchy
  343.  
  344.     | aStream |
  345.     aStream := WriteStream on: (String new: 256).
  346.     self printHierarchyOn: aStream indent: 0.
  347.     ^aStream contents!
  348.  
  349. printHierarchyOn: aStream!
  350.  
  351. printHierarchyOn: aStream indent: i
  352.     aStream crtab: i; nextPutAll: self class name , self auxiliaryPrintInfo!
  353.  
  354. printOn: aStream
  355.     super printOn: aStream.
  356.     aStream nextPutAll: ' (' , self minimumExtent printString , ' -> ' , self extent printString , ')'! !
  357. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  358.  
  359. Interactor class
  360.     instanceVariableNames: ''!
  361.  
  362.  
  363. !Interactor class methodsFor: 'instance creation'!
  364.  
  365. minimumExtent: e
  366.     ^self new minimumExtent: e!
  367.  
  368. new
  369.     ^super new initialize! !
  370.  
  371. !Interactor class methodsFor: 'examples'!
  372.  
  373. activeExample
  374.  
  375.     (TextInteractor new addChild: 'push me!!') active open!
  376.  
  377. allocationExample
  378.  
  379.     | thing |
  380.     thing := AlignedColumnInteractor new.
  381.     1 to: 5 do: [ :allocation | thing
  382.         addChild: ((TextInteractor new addChild: allocation printString) inset) bordered
  383.         allocation: allocation].
  384.     thing open!
  385.  
  386. allocationExample2
  387.  
  388.     | thing |
  389.     thing := AlignedRowInteractor new.
  390.     1 to: 5 do: [ :allocation | thing
  391.         addChild: ((TextInteractor new addChild: allocation printString) inset) bordered
  392.         allocation: allocation].
  393.     ^thing open!
  394.  
  395. borderExample
  396.  
  397.     (ColumnInteractor new
  398.         addChild: ((TextInteractor new
  399.                     addChild: 'aButton') bordered roundBorders borderWidth: 1) active inset;
  400.         addChild: ((TextInteractor new
  401.                     addChild: 'aButton') bordered roundBorders borderWidth: 1) active inset;
  402.         addChild: ((TextInteractor new
  403.                     addChild: 'aButton') bordered roundBorders borderWidth: 1) active inset;
  404.         addChild: ((TextInteractor new
  405.                     addChild: 'aButton') bordered roundBorders borderWidth: 1) active inset)
  406.     minimumExtent: 130@150; open!
  407.  
  408. buttonExample
  409.  
  410.     ((((TextInteractor new
  411.         minimumExtent: 200@50;
  412.         addChild: 'aButton') bordered: 1) inverseBorders) bordered: 3) active
  413.     open!
  414.  
  415. columnExample
  416.  
  417.     (ColumnInteractor new
  418.         addChild: (((TextInteractor new addChild: 'button A') inset: 3) bordered active);
  419.         addChild: (((TextInteractor new addChild: 'button label B'; vRigid: true) inset: 3) bordered active);
  420.         addChild: (((TextInteractor new addChild: 'buttonC'; rigid: true) inset: 3) bordered active))
  421.     open!
  422.  
  423. columnExample2
  424.  
  425.     (ColumnInteractor new
  426.         addChild: (TextInteractor new addChild: 'button A'; vRigid: false) bordered active;
  427.         addChild: (TextInteractor new addChild: 'button B'; vRigid: false) bordered active;
  428.         addChild: (TextInteractor new addChild: 'button C'; vRigid: false) bordered active)
  429.     open!
  430.  
  431. complexExample
  432.     self complexInteractor open!
  433.  
  434. composedTextExample
  435.  
  436.     (StructuredTextInteractor new
  437.         addChild: self exampleString;
  438.         minimumExtent: 200@50;
  439.         inset) open.
  440.     ^(StructuredTextInteractor new
  441.         addChild: self exampleString;
  442.         selected: true;
  443.         inset) open!
  444.  
  445. convertorExample
  446.  
  447.     ((TextInteractor addChild: 'hello world!!')
  448.             textConvertor: [ :string | 'Well, ' , string])
  449.         inset inset inset bordered active open!
  450.  
  451. cyclicButtonExample
  452.  
  453.     | virtual |
  454.     virtual := (VirtualInteractor new
  455.         addChild: ((TextInteractor new addChild: 'one') inset inset inset bordered active onBlock: [ :x | virtual useComponentNext]);
  456.         addChild: ((TextInteractor new addChild: 'two') inset inset inset bordered active onBlock: [ :x | virtual useComponentNext]);
  457.         addChild: ((TextInteractor new addChild: 'three') inset inset inset bordered active onBlock: [ :x | virtual useComponentNext]);
  458.         addChild: ((TextInteractor new addChild: 'four') inset inset inset bordered active onBlock: [ :x | virtual useComponentNext])).
  459.  
  460.     virtual activeChild: virtual children first.
  461.     ^virtual open!
  462.  
  463. emptyExample
  464.  
  465.     (ColumnInteractor new
  466.         addChild: (TextInteractor new addChild: 'hello');
  467.         addChild: RowInteractor new bordered;
  468.         addChild: (TextInteractor new addChild: 'world'))
  469.     open!
  470.  
  471. extensibleExample
  472.  
  473.     "Build a composite interactor with extensible functionality.  Most of the complexity in what follows is to do with disabling the
  474.     add/remove buttons when the extending composite is full/empty."
  475.  
  476.     | labelButtonRow addButton addBlock removeButton removeBlock extender interface dummy buttonCount countBlock |
  477.     buttonCount := 0.
  478.     extender := RowInteractor new extent: 200@50.
  479.     dummy := [ :ignore ].
  480.     addButton := ((TextInteractor on: 'add') minimumExtent: 100@20) active.
  481.     removeButton := ((TextInteractor on: 'remove') minimumExtent: 100@20) active.
  482.     addBlock := [ :sender |
  483.         countBlock value: 1.
  484.         extender installChild: (BorderInteractor on: ((TextInteractor on: 'button') active onBlock: dummy))].
  485.     removeBlock := [ :sender |
  486.         countBlock value: -1.
  487.         extender uninstallLastChild].
  488.     countBlock := [ :step |
  489.         buttonCount := buttonCount + step.
  490.         addButton onBlock: (buttonCount < 6 ifTrue: [addBlock]).
  491.         removeButton onBlock: (buttonCount > 0 ifTrue: [removeBlock])].
  492.  
  493.     labelButtonRow := RowInteractor new
  494.         addChild: (InsetInteractor inset: 5 on: (TextInteractor on: 'extensible interactors...'));
  495.         addChild: (InsetInteractor inset: 5 on: (BorderInteractor on: addButton));
  496.         addChild: (InsetInteractor inset: 5 on: (BorderInteractor on: removeButton)).
  497.  
  498.     countBlock value: 0.
  499.  
  500.     interface := ColumnInteractor new
  501.         addChild: labelButtonRow;
  502.         addChild: extender.
  503.     interface open!
  504.  
  505. fillerExample
  506.  
  507.     ^(RowInteractor new
  508.         addChild: (TextInteractor new addChild: '<<<'; hRigid: true);
  509.         addChild: (self fillerInteractor minimumExtent: 20@0);
  510.         addChild: (TextInteractor new addChild: '>>>'; hRigid: true))
  511.     open!
  512.  
  513. fillerExample2
  514.  
  515.     ^(ColumnInteractor new
  516.         addChild: (TextInteractor new addChild: '^^^'; hRigid: true) bordered;
  517.         addChild: (FillerInteractor new minimumExtent: 20@20);
  518.         addChild: (TextInteractor new addChild: 'vvv'; hRigid: true) bordered)
  519.     open!
  520.  
  521. greyExample
  522.  
  523.     | button1 button2 |
  524.     button1 := (TextInteractor new
  525.         addChild: 'greyable';
  526.         minimumExtent: 200@50)
  527.         inset bordered active selected: nil.
  528.     button2 := (TextInteractor new
  529.         addChild: 'grey it!!';
  530.         minimumExtent: 200@50)
  531.         inset bordered active onBlock: [ :i | button1 selected: nil; render].
  532.     ColumnInteractor new
  533.         addChild: button1;
  534.         addChild: button2;
  535.         open!
  536.  
  537. imageExample
  538.  
  539.     ^(ColumnInteractor new
  540.         addChild: ((TextInteractor on: 'press me') inset: 5);
  541.         addChild: (ImageInteractor new addChild: self exampleImage)
  542.                     bordered active inset)
  543.     open!
  544.  
  545. inputFieldExample
  546.  
  547.     | label accept |
  548.     label := (TextInteractor on: 'input displayed here') vRigid: true.
  549.     accept := [ :sender :value | label addChild: value; render].
  550.     ColumnInteractor new
  551.         addChild: (BorderInteractor on: (InputFieldInteractor new acceptBlock: accept));
  552.         addChild: (BorderInteractor on: label);
  553.         open!
  554.  
  555. insetExample
  556.  
  557.     (((TextInteractor new extent: 200@50; addChild: 'aButton') inset: 10) bordered: 3) active
  558.         open!
  559.  
  560. labelExample
  561.  
  562.     (TextInteractor new addChild: 'hello'; minimumExtent: 200@50) bordered open!
  563.  
  564. mvcExample2
  565.  
  566.     | image view imageLayout viewLayout wrappedImage wrappedView composite window |
  567.  
  568.     image := Image parcPlaceLogo.
  569.  
  570.     imageLayout := LayoutFrame new
  571.         leftFraction: 1.0;
  572.         leftOffset: image width negated.
  573.  
  574.     wrappedImage := BoundedWrapper
  575.         on: image
  576.         in: imageLayout.
  577.  
  578.     composite := CompositePart new.
  579.     composite addWrapper: wrappedImage.
  580.  
  581.     view := TextView
  582.         on: LauncherView comment asComposedText
  583.         aspect: #text
  584.         change: #text:
  585.         menu: nil.
  586.  
  587.     viewLayout := LayoutFrame new
  588.         rightFraction: 1.0;
  589.         rightOffset: image width negated;
  590.         bottomFraction: 1.0.
  591.  
  592.     wrappedView := BorderedWrapper
  593.         on: view
  594.         in: viewLayout.
  595.  
  596.     composite addWrapper: wrappedView.
  597.  
  598.     window := MessageLogger on: (ScheduledWindow new).
  599.     window component: (view).
  600.     window minimumSize: 500@300.
  601.     window open!
  602.  
  603. nestedRadioExample
  604.  
  605.     ^((RowInteractor new)
  606.         addChild: (ColumnInteractor new
  607.             addChild: ((TextInteractor on: 'one') inset bordered active toggle);
  608.             addChild: ((TextInteractor on: 'two') inset bordered active toggle));
  609.         addChild: (ColumnInteractor new
  610.             addChild: ((TextInteractor on: 'three') inset bordered active toggle);
  611.             addChild: ((TextInteractor on: 'four') inset bordered active toggle));
  612.         beRadioGroup)
  613.     open!
  614.  
  615. nestedScrollingExample
  616.  
  617.     ^(RowInteractor new
  618.         addChild: (self complexInteractor4 cachedScrolling
  619.             minimumExtent: 200@200;
  620.             useBothScrollers);
  621.         addChild: ((TextInteractor new minimumExtent: 400@400; addChild: 'Right') cachedScrolling
  622.             minimumExtent: 200@200;
  623.             useBothScrollers)) cachedScrolling useBothScrollers open!
  624.  
  625. nestedScrollingExample2
  626.  
  627.     "This is utterly ludicrous, but should demonstrate that scrollers are at last working..!!"
  628.  
  629.     ((((((((((((TextInteractor addChild: 'Find Me!!') justification: #center)
  630.         inset bordered active inset: 100) rigid
  631.         bordered inverseBorders inset bordered cachedScrolling useBothScrollers minimumExtent: 600@600)
  632.         bordered cachedScrolling useBothScrollers minimumExtent: 550@550)
  633.         bordered cachedScrolling useBothScrollers minimumExtent: 500@500)
  634.         bordered cachedScrolling useBothScrollers minimumExtent: 450@450)
  635.         bordered cachedScrolling useBothScrollers minimumExtent: 400@400)
  636.         bordered cachedScrolling useBothScrollers minimumExtent: 350@350)
  637.         bordered cachedScrolling useBothScrollers minimumExtent: 300@300)
  638.         bordered cachedScrolling useBothScrollers minimumExtent: 250@250)
  639.         bordered cachedScrolling useBothScrollers minimumExtent: 200@200)
  640.         open!
  641.  
  642. objectExample
  643.  
  644.     ^(ObjectInteractor new addChild: 42; justification: #center; displayConvertor: [ :x | (x * 2) printString]) bordered
  645.         active open!
  646.  
  647. penPadButtonExample
  648.     "An example for pcj showing how to create Pen&Pad v5 style buttons"
  649.  
  650.     | top onBlock offBlock |
  651.     top := ColumnInteractor new.
  652.     5 timesRepeat:
  653.         [ | virtual |
  654.         virtual := (VirtualInteractor new
  655.             addChild: ((TextInteractor new addChild: 'one') inset inset inset bordered);
  656.             addChild: ((TextInteractor new addChild: 'two') inset inset inset bordered);
  657.             addChild: ((TextInteractor new addChild: 'three') inset inset inset bordered);
  658.             addChild: ((TextInteractor new addChild: 'four') inset inset inset bordered)).
  659.  
  660.         virtual activeChild: virtual children first.
  661.         onBlock := [ :button | virtual useComponentNext == virtual children first ifTrue: [button deselect]].
  662.         offBlock := [ :button | virtual useComponentIndex: 1].
  663.         top addChild: (virtual active cyclic onBlock: onBlock; offBlock: offBlock)].
  664.  
  665.     top beRadioGroup open!
  666.  
  667. radioExample
  668.     | top one two |
  669.     top := ColumnInteractor new.
  670.     top
  671.         addChild: (one := (TextInteractor on: 'one') inset bordered active toggle);
  672.         addChild: (two := (TextInteractor on: 'two') inset bordered active toggle).
  673.     one
  674.         onBlock: [ :i | Transcript cr; show: 'one on'];
  675.         offBlock: [ :i | Transcript cr; show: 'one off'].
  676.     two
  677.         onBlock: [ :i | "self halt." Transcript cr; show: 'two on'];
  678.         offBlock: [ :i | Transcript cr; show: 'two off'].
  679.     top beRadioGroup; open!
  680.  
  681. reallocationExample
  682.  
  683.     | one two |
  684.     one := ((ColumnInteractor new)
  685.         addChild: (AlignedRowInteractor new
  686.             addChild: ((TextInteractor on: 'short') bordered active toggle);
  687.             addChild: ((TextInteractor on: 'far longer than the previous utterly tiny field (by comparison)') bordered active toggle));
  688.         addChild: (AlignedRowInteractor new
  689.             addChild: ((TextInteractor on: 'weeny') bordered active toggle);
  690.             addChild: ((TextInteractor on: 'tiny') bordered active toggle));
  691.         beRadioGroup).
  692.  
  693.     two := ((DynamicColumnInteractor new)
  694.         addChild: (AlignedRowInteractor new
  695.             addChild: ((TextInteractor on: 'short') bordered active toggle);
  696.             addChild: ((TextInteractor on: 'far longer than the previous utterly tiny field (by comparison)') bordered active toggle));
  697.         addChild: (AlignedRowInteractor new
  698.             addChild: ((TextInteractor on: 'weeny') bordered active toggle);
  699.             addChild: ((TextInteractor on: 'tiny') bordered active toggle));
  700.         beRadioGroup).
  701.  
  702.     one open.
  703.     two open!
  704.  
  705. reallocationExample2
  706.  
  707.  
  708.     (DynamicColumnInteractor new
  709.         addChild: (AlignedRowInteractor new
  710.             addChild: ((TextInteractor on: 'short') bordered active toggle);
  711.             addChild: ((TextInteractor on: 'a bit longer') bordered active toggle));
  712.         addChild: (TextInteractor on: 'boom!!') inset bordered;
  713.         addChild: (AlignedRowInteractor new
  714.             addChild: ((TextInteractor on: 'longish') bordered active toggle);
  715.             addChild: ((TextInteractor on: 'teeny') bordered active toggle)))
  716.     open!
  717.  
  718. reallocationExample3
  719.     "This is DESIGNED to break!!!!!!"
  720.  
  721.  
  722.     (DynamicColumnInteractor new
  723.         addChild: (AlignedRowInteractor new
  724.             addChild: (AlignedRowInteractor new
  725.                 addChild: ((TextInteractor on: 'short') bordered active toggle);
  726.                 addChild: ((TextInteractor on: 'a bit longer') bordered active toggle));
  727.             addChild: (TextInteractor on: 'boom!!') bordered;
  728.             addChild: (AlignedRowInteractor new
  729.                 addChild: ((TextInteractor on: 'longish') bordered active toggle);
  730.                 addChild: ((TextInteractor on: 'teeny') bordered active toggle)));
  731.         addChild: (AlignedRowInteractor new
  732.             addChild: (AlignedRowInteractor new
  733.                 addChild: ((TextInteractor on: 'short') bordered active toggle);
  734.                 addChild: ((TextInteractor on: 'a bit longer') bordered active toggle));
  735.             addChild: (TextInteractor on: 'boom!!') bordered;
  736.             addChild: (AlignedRowInteractor new
  737.                 addChild: ((TextInteractor on: 'longish') bordered active toggle);
  738.                 addChild: ((TextInteractor on: 'teeny') bordered active toggle))))
  739.     open!
  740.  
  741. rowExample
  742.  
  743.     (RowInteractor new
  744.         addChild: (TextInteractor new addChild: 'button 1') bordered active;
  745.         addChild: (TextInteractor new addChild: 'button 2'; hRigid: true) bordered active;
  746.         addChild: (TextInteractor new addChild: 'button 3'; hRigid: true) bordered active)
  747.     open!
  748.  
  749. scrollingExample
  750.  
  751.     ((TextInteractor new addChild: 'scroll me!!'; minimumExtent: 400@400; yourself) cachedScrolling
  752.         minimumExtent: 50@50;
  753.         useBothScrollers) bordered open!
  754.  
  755. scrollingExample2
  756.  
  757.     RowInteractor new
  758.         addChild: ((ColumnInteractor new
  759.             addChild: ((TextInteractor minimumExtent: 100@100) rigid: true; addChild: 'Above') bordered active;
  760.             addChild: ((TextInteractor minimumExtent: 100@100) rigid: true; addChild: 'Below') bordered active)
  761.                             cachedScrolling useBothScrollers minimumExtent: 50@50);
  762.         addChild: (((TextInteractor minimumExtent: 100@100) rigid: false; addChild: 'Right')
  763.                             bordered active cachedScrolling useBothScrollers minimumExtent: 50@50);
  764.         open!
  765.  
  766. scrollingExample3
  767.  
  768.      (RowInteractor new
  769.         addChild: (self complexInteractor4 cachedScrolling
  770.             minimumExtent: 50@50;
  771.             useBothScrollers);
  772.         addChild: ((TextInteractor new minimumExtent: 400@400; addChild: 'Right') cachedScrolling
  773.             minimumExtent: 50@50;
  774.             useBothScrollers)) open!
  775.  
  776. scrollingStructuredTextExample
  777.  
  778.     (StructuredTextInteractor new
  779.         addChild: (NLP penPadPrint: TestEntity);
  780.         selectionEmphasis: #(italic underline bold);
  781.         selectionBlock: [ :int :bog | Transcript cr; show: bog subject printString];
  782.         minimumExtent: 200@50;
  783.         inset) cachedScrolling useBothScrollers open!
  784.  
  785. simpleScrollingExample
  786.  
  787.     ((TextInteractor new addChild: 'scroll me!!'; minimumExtent: 400@400; yourself) scrolling
  788.         minimumExtent: 50@50;
  789.         useBothScrollers) bordered open!
  790.  
  791. simpleScrollingExample2
  792.  
  793.     RowInteractor new
  794.         addChild: ((ColumnInteractor new
  795.             addChild: ((TextInteractor minimumExtent: 100@100) rigid: true; addChild: 'Above') bordered active;
  796.             addChild: ((TextInteractor minimumExtent: 100@100) rigid: true; addChild: 'Below') bordered active)
  797.                             scrolling useBothScrollers minimumExtent: 50@50);
  798.         addChild: (((TextInteractor minimumExtent: 100@100) rigid: false; addChild: 'Right')
  799.                             bordered active scrolling useBothScrollers minimumExtent: 50@50);
  800.         open!
  801.  
  802. simpleScrollingExample3
  803.  
  804.      (RowInteractor new
  805.         addChild: (self complexInteractor4 scrolling
  806.             minimumExtent: 50@50;
  807.             useBothScrollers);
  808.         addChild: ((TextInteractor new minimumExtent: 400@400; addChild: 'Right') scrolling
  809.             minimumExtent: 50@50;
  810.             useBothScrollers)) open!
  811.  
  812. simpleScrollingStructuredTextExample
  813.  
  814.     (StructuredTextInteractor new
  815.         addChild: (NLP penPadPrint: TestEntity);
  816.         selectionEmphasis: #(italic underline bold);
  817.         selectionBlock: [ :int :bog | Transcript cr; show: bog subject printString];
  818.         minimumExtent: 200@50;
  819.         inset:60) scrolling useBothScrollers open!
  820.  
  821. sliderBoundedExample
  822.  
  823.     (SliderInteractor new
  824.         minVal: 50;
  825.         maxVal: 500;
  826.         valueBlock: [ :i :x | Transcript cr; show: x printString]; currentValue: 50) open.!
  827.  
  828. sliderExample
  829.  
  830.     (SliderInteractor new valueBlock: [ :i :x | Transcript cr; show: x printString]; currentValue: 50) open.!
  831.  
  832. sliderExample2
  833.     | slider up down |
  834.     slider := SliderInteractor new
  835.         incrementSize: 5;
  836.         valueBlock: [ :i :x | Transcript cr; show: x printString].
  837.     up := (TextInteractor addChild: '+') inset bordered active autoRepeat onBlock: [ :x | slider increment].
  838.     down := (TextInteractor addChild: '-') inset bordered active autoRepeat onBlock: [ :x | slider decrement].
  839.     ^(RowInteractor new
  840.         addChild: (ColumnInteractor new
  841.             addChild: up;
  842.             addChild: down);
  843.         addChild: slider)
  844.     open!
  845.  
  846. sliderExample3
  847.     | slider up down cancel |
  848.     slider := SliderInteractor new
  849.         incrementSize: 5;
  850.         valueBlock: [ :i :x | Transcript cr; show: x printString].
  851.     up := (TextInteractor addChild: '+') inset bordered active autoRepeat onBlock: [ :x | slider increment].
  852.     down := (TextInteractor addChild: '-') inset bordered active autoRepeat onBlock: [ :x | slider decrement].
  853.     cancel := (TextInteractor addChild: 'clear') inset bordered active autoRepeat onBlock: [ :x | slider clearValue].
  854.     ^(RowInteractor new
  855.         addChild: (ColumnInteractor new
  856.             addChild: (RowInteractor new
  857.                 addChild: down;
  858.                 addChild: up);
  859.             addChild: cancel);
  860.         addChild: slider)
  861.     open!
  862.  
  863. sliderExample4
  864.     | slider up down cancel typer |
  865.     slider := SliderInteractor new
  866.         incrementSize: 5;
  867.         valueBlock: [ :i :x | Transcript cr; show: x printString].
  868.     up := (TextInteractor addChild: '+') inset bordered active autoRepeat onBlock: [ :x | slider increment].
  869.     down := (TextInteractor addChild: '-') inset bordered active autoRepeat onBlock: [ :x | slider decrement].
  870.     cancel := (TextInteractor addChild: 'clear') inset bordered active autoRepeat onBlock: [ :x | slider clearValue].
  871.     typer := InputFieldInteractor new.
  872.     typer acceptBlock: [ :i :x | slider newValue: (Integer readFrom: (ReadStream on: x))].
  873.     ^(RowInteractor new
  874.         addChild: (ColumnInteractor new
  875.             addChild: (RowInteractor new
  876.                 addChild: down;
  877.                 addChild: up);
  878.             addChild: cancel);
  879.         addChild: slider;
  880.         addChild: typer inset bordered)
  881.     open!
  882.  
  883. sliderExample5
  884.  
  885.     (ColumnInteractor new
  886.         addChild: (SliderInteractor new valueBlock: [ :i :x | Transcript cr; show: x printString]; currentValue: 50);
  887.         addChild: (SliderInteractor new valueBlock: [ :i :x | Transcript cr; show: x printString]; currentValue: 50);
  888.         addChild: (FillerInteractor minimumExtent: 50@50))
  889.      open.!
  890.  
  891. sliderExample6
  892.     | slider |
  893.     (RowInteractor new
  894.         addChild: (slider := SliderInteractor new
  895.                     valueBlock: [ :i :x | Transcript cr; show: x printString]; currentValue: 50);
  896.         addChild: (InputFieldInteractor new
  897.                     acceptBlock: [ :i :s |
  898.                         slider newValue: (Number readFrom: s readStream).
  899.                         i setText: ''; render];
  900.                     minimumExtent: 50@0)) open.!
  901.  
  902. sliderFixedPointExample
  903.  
  904.     (FixedPointSliderInteractor new valueBlock: [ :i :x | Transcript cr; show: x printString]; currentValue: 50) open.!
  905.  
  906. sliderFixedPointExample2
  907.  
  908.     (FixedPointSliderInteractor new
  909.         scaling: 100;
  910.         valueBlock: [ :i :x | Transcript cr; show: x printString]; currentValue: 50) open.!
  911.  
  912. structuredTextExample
  913.  
  914.     (StructuredTextInteractor new
  915.         addChild: (NLP penPadPrint: TestEntity);
  916.         selectionEmphasis: #(italic underline bold);
  917.         selectionBlock: [ :int :bog | Transcript cr; show: bog subject printString];
  918.         minimumExtent: 200@50;
  919.         inset) open!
  920.  
  921. textExample
  922.  
  923.     TextInteractor new
  924.         addChild: 'not selected';
  925.         minimumExtent: 200@50;
  926.         justification: #center;
  927.         open.
  928.     ^TextInteractor new
  929.         addChild: 'selected';
  930.         selected: true;
  931.         open!
  932.  
  933. toggleExample
  934.  
  935.     ^((TextInteractor on: 'toggle') inset bordered active toggle
  936.         onBlock: [ :x | Transcript tab; show: 'ON!!'];
  937.         offBlock: [ :x | Transcript tab; show: 'off!!!!!!'])
  938.     open!
  939.  
  940. virtualExample
  941.  
  942.     "Build a virtual interactor with obviously varying functionality"
  943.  
  944.     | label virtual top |
  945.  
  946.     label := TextInteractor new addChild: 'virtual interactions'; justification: #center; textStyle: (TextAttributes styleNamed: #large).
  947.  
  948.     (virtual := VirtualInteractor new
  949.         addChild: (TextInteractor new addChild: 'Inactive Text Pane');
  950.         addChild: (ColumnInteractor new
  951.             addChild: (TextInteractor new addChild: 'Active...');
  952.             addChild: (RowInteractor new
  953.                 addChild: (TextInteractor new addChild: '1'; justification: #right) inset bordered active;
  954.                 addChild: (TextInteractor new addChild: '2'; justification: #center) inset bordered active;
  955.                 addChild: (TextInteractor new addChild: '3'; justification: #left) inset bordered active);
  956.             addChild: (TextInteractor new addChild: '...buttons'));
  957.         addChild: (RowInteractor new
  958.             addChild: (TextInteractor new addChild: 'More...');
  959.             addChild: (RowInteractor new
  960.                 addChild: (TextInteractor new addChild: 'A') inset bordered active;
  961.                 addChild: (TextInteractor new addChild: 'B') inset bordered active;
  962.                 addChild: (TextInteractor new addChild: 'C') inset bordered active);
  963.             addChild: (TextInteractor new addChild: '...buttons!!'))).
  964.  
  965.     (top := ColumnInteractor new)
  966.         addChild: label;
  967.         addChild: (RowInteractor new
  968.             addChild: virtual bordered inverseBorders;
  969.             addChild: (ColumnInteractor new
  970.                 addChild: ((TextInteractor new addChild: 'one'; rigid: false) inset bordered recessedBorders active toggle onBlock:
  971.                             [ :me | virtual useComponentIndex: 1; windowLabel: 'Simple Text']);
  972.                 addChild: ((TextInteractor new addChild: 'two'; rigid: false) inset bordered recessedBorders active toggle onBlock:
  973.                             [ :me | virtual useComponentIndex: 2; windowLabel: 'Horizontal Buttons']);
  974.                 addChild: ((TextInteractor new addChild: 'three'; rigid: false) inset bordered recessedBorders active toggle onBlock:
  975.                             [ :me | virtual useComponentIndex: 3; windowLabel: 'Vertical Buttons']);
  976.                 beRadioGroup)).
  977.  
  978.     virtual activeChild: nil.
  979.  
  980.     top open windowLabel: 'No Component'!
  981.  
  982. wrappedTextExample
  983.  
  984.     WrappedTextInteractor new
  985.         addChild: self exampleString;
  986.         minimumExtent: 100@50;
  987.         open!
  988.  
  989. xServerThrashingExample
  990.  
  991.     | top |
  992.     top := RowInteractor new.
  993.     17 timesRepeat:
  994.         [ | bottom |
  995.         bottom := ColumnInteractor new.
  996.         8 timesRepeat: [bottom addChild:
  997.                         ((TextInteractor on: 'hello') minimumExtent: 500@300) cachedScrolling useBothScrollers bordered].
  998.         top addChild: bottom].
  999.     top cachedScrolling useBothScrollers open! !
  1000.  
  1001. !Interactor class methodsFor: 'examples-private'!
  1002.  
  1003. complexInteractor
  1004.     ^ColumnInteractor new
  1005.         addChild: (RowInteractor new
  1006.             addChild: (TextInteractor new addChild: '1'; hRigid: false; vRigid: false) inset bordered active;
  1007.             addChild: (TextInteractor new addChild: '2'; hRigid: true; vRigid: false) inset bordered;
  1008.             addChild: (TextInteractor new addChild: '3'; hRigid: false; vRigid: false) inset bordered);
  1009.         addChild: (RowInteractor new
  1010.             addChild: (TextInteractor new addChild: '4'; hRigid: false; vRigid: true) inset bordered;
  1011.             addChild: (TextInteractor new addChild: '5'; hRigid: true; vRigid: true) inset bordered;
  1012.             addChild: (TextInteractor new addChild: '6'; hRigid: false; vRigid: true) inset bordered);
  1013.     addChild: (RowInteractor new
  1014.         addChild: (TextInteractor new addChild: '7'; hRigid: false; vRigid: false) inset bordered;
  1015.         addChild: (TextInteractor new addChild: '8'; hRigid: true; vRigid: false) inset bordered;
  1016.         addChild: (TextInteractor new addChild: '9'; hRigid: false; vRigid: false) inset bordered)!
  1017.  
  1018. complexInteractor2
  1019.  
  1020.     ^RowInteractor new
  1021.         addChild: (ColumnInteractor new
  1022.             addChild: (TextInteractor new addChild: '1'; hRigid: true; vRigid: true) inset bordered active;
  1023.             addChild: (TextInteractor new addChild: '2'; hRigid: true; vRigid: false) inset bordered;
  1024.             addChild: (TextInteractor new addChild: '3'; hRigid: true; vRigid: true) inset bordered);
  1025.         addChild: (ColumnInteractor new
  1026.             addChild: (TextInteractor new addChild: '4'; hRigid: false; vRigid: true) inset bordered;
  1027.             addChild: (TextInteractor new addChild: '5'; hRigid: false; vRigid: false) inset bordered;
  1028.             addChild: (TextInteractor new addChild: '6'; hRigid: false; vRigid: true) inset bordered);
  1029.         addChild: (ColumnInteractor new
  1030.             addChild: (TextInteractor new addChild: '7'; hRigid: true; vRigid: true) inset bordered;
  1031.             addChild: (TextInteractor new addChild: '8'; hRigid: true; vRigid: false) inset bordered;
  1032.             addChild: (TextInteractor new addChild: '9'; hRigid: true; vRigid: true) inset bordered)!
  1033.  
  1034. complexInteractor3
  1035.     ^ColumnInteractor new
  1036.         addChild: self complexInteractor;
  1037.         addChild: self complexInteractor2;
  1038.         addChild: self complexInteractor!
  1039.  
  1040. complexInteractor4
  1041.     ^RowInteractor new
  1042.         addChild: self complexInteractor3;
  1043.         addChild: self complexInteractor3;
  1044.         addChild: self complexInteractor3!
  1045.  
  1046. exampleImage
  1047.  
  1048.     | image bits |
  1049.     image := Image parcPlaceLogo shrunkenBy: 2@2.
  1050.     bits := image bitsInstVar.
  1051.     1 to: bits size do: [ :i | bits at: i put: 255 - (bits at: i)].
  1052.     ^image!
  1053.  
  1054. exampleString
  1055.  
  1056.     ^
  1057. 'People prefer to refer to hosts using a name rather than a
  1058. string of digits.  So IP implementations usually have some sort of
  1059. name-to-address directory in which an address can be looked up
  1060. dynamically.
  1061.  
  1062. To deal with the case where you have a host number but no name, 
  1063. all the routines which deal with host names (which are Strings) can
  1064. accept numeric strings in canonical format (i.e. 192.9.100.4).
  1065.  
  1066. The class protocol ''naming utilities'' has methods to convert to/from
  1067. host-names and host-addresses.
  1068. '!
  1069.  
  1070. fillerInteractor
  1071.     ^FillerInteractor new!
  1072.  
  1073. silly
  1074.  
  1075.     | window bounds o1 o2 p1 p2 d1 d2 gc r sensor |
  1076.     r := Random new.
  1077.     bounds := (window := Window currentWindow) bounds.
  1078.     gc := window graphicsContext.
  1079.     gc lineWidth: 25.
  1080.     sensor := window sensor.
  1081.     p1 := 0.0@0.0.
  1082.     p2 := 0.0@0.0.
  1083.     d1 := r next @ r next.
  1084.     d2 := r next @ r next.
  1085.     [sensor redButtonPressed not] whileTrue: [
  1086.         gc    paint: ColorValue black;
  1087.             displayLineFrom: (p1 x asInteger)@(p1 y asInteger) to: (p2 x asInteger)@(p2 y asInteger).
  1088.         o1 := p1 copy.
  1089.         o2 := p2 copy.
  1090.         p1 := p1 + d1.
  1091.         p2 := p2 + d2.
  1092.         p1 x > bounds corner x ifTrue: [d1 x: d1 x negated].
  1093.         p1 y > bounds corner y ifTrue: [d1 y: d1 y negated].
  1094.         p2 x > bounds corner x ifTrue: [d2 x: d2 x negated].
  1095.         p2 y > bounds corner y ifTrue: [d2 y: d2 y negated].
  1096.         p1 x < bounds origin x ifTrue: [d1 x: d1 x negated].
  1097.         p1 y < bounds origin y ifTrue: [d1 y: d1 y negated].
  1098.         p2 x < bounds origin x ifTrue: [d2 x: d2 x negated].
  1099.         p2 y < bounds origin y ifTrue: [d2 y: d2 y negated].
  1100.         gc paint: ColorValue white;
  1101.             displayLineFrom: (o1 x asInteger)@(o1 y asInteger) to: (o2 x asInteger)@(o2 y asInteger)].
  1102.     window refresh! !
  1103.  
  1104. !Interactor class methodsFor: 'development support'!
  1105.  
  1106. closeCorpses
  1107.  
  1108.     (StandardSystemController allInstances select: [ :ctrl | ctrl model class == RootInteractor]) do: [ :ctrl | ctrl close]!
  1109.  
  1110. fallin: dict from: object
  1111.  
  1112.     | i |
  1113.     (i := object allInstances) isEmpty ifFalse: [dict at: object printString asSymbol put: i]!
  1114.  
  1115. inspectFallout
  1116.  
  1117.     | a |
  1118.     ObjectMemory compactingGC; globalGarbageCollect.
  1119.     a := self snarfFallout.
  1120.     a isEmpty ifFalse: [a inspect]!
  1121.  
  1122. releaseFallout
  1123.  
  1124.     | snarf |
  1125.     ((snarf := self snarfFallout) at: #RootInteractor ifAbsent: [#()]) do:
  1126.         [ :root | root window isNil ifFalse: [root window close]].
  1127.     snarf  do: [ :c | c do: [ :x | x release]].
  1128.     self inspectFallout!
  1129.  
  1130. snarfFallout
  1131.  
  1132.     | a |
  1133.     Cursor execute showWhile: [
  1134.         a := Dictionary new.
  1135.         self
  1136.             fallin: a from: ActiveInteractor;
  1137.             fallin: a from: ColumnInteractor;
  1138.             fallin: a from: CompositeInteractor;
  1139.             fallin: a from: FillerInteractor;
  1140.             fallin: a from: Interactor;
  1141.             fallin: a from: InteractorController;
  1142.             fallin: a from: InteractorView;
  1143.             fallin: a from: MVCInteractor;
  1144.             fallin: a from: StemInteractor;
  1145.             fallin: a from: RootInteractor;
  1146.             fallin: a from: RowInteractor;
  1147.             fallin: a from: CachedScrollingInteractor;
  1148.             fallin: a from: ScrollingInteractor;
  1149.             fallin: a from: SimpleInteractor;
  1150.             fallin: a from: HScrollbar;
  1151.             fallin: a from: HScroller;
  1152.             fallin: a from: PButton;
  1153.             fallin: a from: PScrollbar;
  1154.             fallin: a from: PScroller;
  1155.             fallin: a from: ScrollerSensor;
  1156.             fallin: a from: VScrollbar;
  1157.             fallin: a from: VScroller].
  1158.     ^a! !
  1159.  
  1160. !Interactor class methodsFor: 'fileIn/Out'!
  1161.  
  1162. fileOutInteractors
  1163.  
  1164.     #('Interactors-Framework' 'Interactors-Scrolling' 'Interactors-Support' 'Interactors-PenPad')
  1165.         do: [:category || file |
  1166.                 file := SourceCodeStream on: (category, '.st') asFilename writeStream.
  1167.                 [Smalltalk organization fileOutCategorySource: category on: file]
  1168.                     valueNowOrOnUnwindDo: [file close]]! !
  1169.  
  1170. !Interactor class methodsFor: 'development utilitites'!
  1171.  
  1172. allAccessesTo: instVarName
  1173.     | coll |
  1174.     coll := OrderedCollection new.
  1175.     Cursor execute showWhile: [
  1176.         self allSubclasses
  1177.             add: self;
  1178.             do: [:class | (class whichSelectorsAccess: instVarName) do: [:sel | coll add: class name , ' ' , sel]]].
  1179.     ^coll!
  1180.  
  1181. allCallsOn: aLiteral 
  1182.     | aSortedCollection |
  1183.     aSortedCollection := SortedCollection new.
  1184.     Cursor execute showWhile: 
  1185.         [self allSubclasses
  1186.             add: self;
  1187.             do: [:class | (class whichSelectorsReferTo: aLiteral) do: 
  1188.                             [:sel | aSortedCollection add: class name , ' ' , sel]]].
  1189.     ^aSortedCollection!
  1190.  
  1191. allImplementorsOf: aSelector  
  1192.     | aCollection |
  1193.     aCollection := SortedCollection new.
  1194.     Cursor execute showWhile:
  1195.         [self allSubclasses
  1196.             add: self;
  1197.             do: [:class | (class includesSelector: aSelector)
  1198.                             ifTrue: [aCollection add: class name, ' ', aSelector]]].
  1199.     ^aCollection!
  1200.  
  1201. browseAllAccesses
  1202.     self browseAllAccessesTo: (DialogView request: 'browse which instance variable?')!
  1203.  
  1204. browseAllAccessesTo: instanceVariable
  1205.     ^MethodListBrowser
  1206.         openListBrowserOn: (self allAccessesTo: instanceVariable)
  1207.         label: instanceVariable
  1208.         initialSelection: instanceVariable!
  1209.  
  1210. browseAllImplementors
  1211.     self browseAllImplementorsOf: (DialogView request: 'browse implementors of which selector?') asSymbol!
  1212.  
  1213. browseAllImplementorsOf: selector
  1214.     MethodListBrowser
  1215.         openListBrowserOn: (self allImplementorsOf: selector)
  1216.         label: 'Implementors of ' , selector!
  1217.  
  1218. browseAllSenders
  1219.     self browseAllSendersOf: (DialogView request: 'browse senders of which selector?') asSymbol!
  1220.  
  1221. browseAllSendersOf: aSymbolOrAssociation
  1222.     | label key selection |
  1223.     (aSymbolOrAssociation isMemberOf: Association)
  1224.         ifTrue: [key := aSymbolOrAssociation key.
  1225.                 label := 'Users of ' , key asString.
  1226.                 selection := key]
  1227.         ifFalse: [key := aSymbolOrAssociation.
  1228.                 label := 'References to ', key asString.
  1229.                 selection := key asSymbol keywords first].
  1230.  
  1231.  
  1232.     ^ MethodListBrowser
  1233.         openListBrowserOn: (self allCallsOn: aSymbolOrAssociation)
  1234.         label: label
  1235.         initialSelection: selection!
  1236.  
  1237. compareClass: classA with: classB
  1238.     | selectorsA selectorsB notInA notInB report commonSelectors |
  1239.     report := WriteStream on: (String new: 256).
  1240.     selectorsA := classA selectors.
  1241.     selectorsB := classB selectors.
  1242.     notInA := selectorsB select: [ :sel | (selectorsA includes: sel) not].
  1243.     notInB := selectorsA select: [ :sel | (selectorsB includes: sel) not].
  1244.     report nextPutAll: 'selectors missing in ' , classA printString , ':'.
  1245.     notInA do: [ :sel | report crtab; nextPutAll: sel asString].
  1246.     report cr; cr; nextPutAll: 'selectors missing in ' , classB printString , ':'.
  1247.     notInB do: [ :sel | report crtab; nextPutAll: sel asString].
  1248.     report cr; cr; nextPutAll: 'changed methods'.
  1249.     commonSelectors := selectorsA asSet addAll: selectorsB asSet.
  1250.     commonSelectors removeAll: notInA asSet.
  1251.     notInB asSet do: [ :sel | (commonSelectors includes: sel) ifTrue: [commonSelectors remove: sel]].
  1252.     commonSelectors do: [ :sel |
  1253.         (Interactor compiledMethod: (classA compiledMethodAt: sel) hasBytesOf: (classB compiledMethodAt: sel))
  1254.             ifFalse: [report crtab; nextPutAll: sel printString]].
  1255.     report cr.
  1256.     ^report contents!
  1257.  
  1258. compiledMethod: cm1 hasBytesOf: cm2
  1259.     cm1 basicSize == cm2 basicSize ifFalse: [^false].
  1260.     1 to: cm1 basicSize do: [ :index | (cm1 basicAt: index) == (cm2 basicAt: index) ifFalse: [^false]].
  1261.     ^true! !
  1262.  
  1263. Interactor subclass: #RootInteractor
  1264.     instanceVariableNames: 'label lookPreferences component previousSelectionPoint previousSelectionInteractor previousSelectionTime '
  1265.     classVariableNames: ''
  1266.     poolDictionaries: ''
  1267.     category: 'Interactors-Framework'!
  1268.  
  1269.  
  1270. !RootInteractor methodsFor: 'initialize-release'!
  1271.  
  1272. initialize
  1273.     self previousSelectionTime: Time millisecondClockValue.
  1274.     super initialize.
  1275.     self lookPreferences: LookPreferences defaultForWindows!
  1276.  
  1277. release
  1278.     component release.
  1279.     component := previousSelectionInteractor := nil.
  1280.     super release! !
  1281.  
  1282. !RootInteractor methodsFor: 'hierarchy'!
  1283.  
  1284. installComposites
  1285.  
  1286.     component installComposites!
  1287.  
  1288. installHierarchy
  1289.  
  1290.     "The installation of parents should be distributed accross the addition of
  1291.     children, with each parent handling the installation of itself as the guardian
  1292.     of its offspring."
  1293.  
  1294.     component parent: self; installHierarchy.
  1295.     "self hierarchyString inspect"!
  1296.  
  1297. installSensor: aSensor
  1298.  
  1299.     self sensor: aSensor.
  1300.     component installSensor: aSensor! !
  1301.  
  1302. !RootInteractor methodsFor: 'accessing'!
  1303.  
  1304. addChild: c 
  1305.     component isNil
  1306.         ifFalse: [self error: 'Duplicate component in RootInteractor!!']
  1307.         ifTrue: [self component: c]!
  1308.  
  1309. addChild: child beforeClass: class
  1310.     ^self addChild: child!
  1311.  
  1312. bounds
  1313.     ^Point zero extent: self extent!
  1314.  
  1315. component
  1316.     ^component!
  1317.  
  1318. component: c
  1319.     component := c!
  1320.  
  1321. graphicsContext
  1322.     ^self window graphicsContext!
  1323.  
  1324. graphicsContextFor: anInteractor
  1325.     ^self graphicsContext!
  1326.  
  1327. lookPreferences
  1328.     ^lookPreferences!
  1329.  
  1330. lookPreferences: lp
  1331.     lookPreferences := lp!
  1332.  
  1333. minimumExtent
  1334.     ^self extent!
  1335.  
  1336. previousSelectionInteractor
  1337.     ^previousSelectionInteractor!
  1338.  
  1339. previousSelectionInteractor: aInteractor
  1340.     previousSelectionInteractor := aInteractor!
  1341.  
  1342. previousSelectionPoint
  1343.     ^previousSelectionPoint!
  1344.  
  1345. previousSelectionPoint: aPoint
  1346.     previousSelectionPoint := aPoint!
  1347.  
  1348. previousSelectionTime
  1349.     ^previousSelectionTime!
  1350.  
  1351. previousSelectionTime: aTime
  1352.     previousSelectionTime := aTime!
  1353.  
  1354. rootInteractor!
  1355.  
  1356. windowLabel
  1357.     ^label isNil
  1358.         ifTrue: ['Interact with me!!']
  1359.         ifFalse: [label]!
  1360.  
  1361. windowLabel: l
  1362.     label := l.
  1363.     self setLabel! !
  1364.  
  1365. !RootInteractor methodsFor: 'scheduling'!
  1366.  
  1367. open
  1368.     "This is the big crunch - compose the component, create
  1369.     a Pixmap to hold the visual representation, then create
  1370.     and schedule a window to realize the interactor."
  1371.  
  1372.     | view |
  1373.     self
  1374.         installComposites;
  1375.         installHierarchy;
  1376.         defaultExtent: component computeExtent.
  1377.     window := ScheduledWindow new.
  1378.     self component installWindow: window.
  1379.     (component computeBounds: (0@0 extent: self extent)) area < 100 ifTrue: [self uimsError].
  1380.     view := InteractorView model: self interactor: self.
  1381.     window controller model: view model.
  1382.     window component: view.
  1383.     self setLabel.
  1384.     window minimumSize: component extent.
  1385.     self graphicsContext font: FontDescription default.
  1386.     self installSensor: window sensor.
  1387.     "component renderOn: self graphicsContext."
  1388.     window open!
  1389.  
  1390. setLabel
  1391.  
  1392.     self window isNil ifFalse: [self window label: self windowLabel]! !
  1393.  
  1394. !RootInteractor methodsFor: 'resizing'!
  1395.  
  1396. displayOn: aGC
  1397.  
  1398.     aGC font: FontDescription default.
  1399.     component renderOn: aGC!
  1400.  
  1401. recompose
  1402.     component computeExtent.
  1403.     ^self recomposeIn: self bounds!
  1404.  
  1405. recomposeIn: newBounds
  1406.     "My window has changed extent - rebuild my pixmap, recompose my
  1407.     interior, then redisplay myself."
  1408.  
  1409.     | gc |
  1410.     self extent: newBounds extent.
  1411.     component computeBounds: newBounds.
  1412.     (gc := self graphicsContext) font: FontDescription default.
  1413.     "component renderOn: gc."
  1414.     "gc flush"! !
  1415.  
  1416. !RootInteractor methodsFor: 'printing'!
  1417.  
  1418. printHierarchyOn: aStream indent: i
  1419.  
  1420.     aStream crtab: i; nextPutAll: 'Root ' , self auxiliaryPrintInfo.
  1421.     component printHierarchyOn: aStream indent: i+1! !
  1422.  
  1423. !RootInteractor methodsFor: 'event enquiry'!
  1424.  
  1425. interactorAt: aPoint
  1426.  
  1427.     ^component interactorAt: aPoint! !
  1428.  
  1429. !RootInteractor methodsFor: 'event response'!
  1430.  
  1431. keyboardDown: aPoint
  1432.  
  1433.     | actor |
  1434.     (actor := self interactorAt: aPoint) notNil
  1435.         ifTrue: [actor keyboardDown]
  1436.         ifFalse: [self error: 'default keyboard processing not installed!!!!!!']!
  1437.  
  1438. operateDown: aPoint
  1439.  
  1440.     | actor |
  1441.     (actor := self interactorAt: aPoint) notNil ifTrue: [actor operateDown]!
  1442.  
  1443. selectDown: aPoint
  1444.  
  1445.     | actor |
  1446.     (actor := self interactorAt: aPoint) notNil
  1447.         ifTrue:
  1448.             [(self previousSelectionPoint = aPoint
  1449.                     and: [self previousSelectionInteractor = actor
  1450.                     and: [Time millisecondClockValue - self previousSelectionTime < self selectionDelay]])
  1451.                 ifTrue: [actor selectDownDown]
  1452.                  ifFalse: [actor selectDown]].
  1453.     self
  1454.         previousSelectionPoint: aPoint;
  1455.         previousSelectionInteractor: actor;
  1456.         previousSelectionTime: Time millisecondClockValue!
  1457.  
  1458. startUp: aPoint
  1459.  
  1460.     | actor |
  1461.     (actor := self interactorAt: aPoint) notNil ifTrue: [actor startUp]! !
  1462.  
  1463. !RootInteractor methodsFor: 'rendering'!
  1464.  
  1465. damaged
  1466.  
  1467.     "If double buffering is in use, update the view on the screen based on the
  1468.     current damage; otherwise ignore."
  1469.  
  1470.     "self flush"! !
  1471.  
  1472. !RootInteractor methodsFor: 'look and feel'!
  1473.  
  1474. selectionDelay
  1475.     ^200 "ms"! !
  1476.  
  1477. !RootInteractor methodsFor: 'testing'!
  1478.  
  1479. hasIndirectParent: anInteractor
  1480.     ^self == anInteractor! !
  1481. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1482.  
  1483. RootInteractor class
  1484.     instanceVariableNames: ''!
  1485.  
  1486.  
  1487. !RootInteractor class methodsFor: 'instance creation'!
  1488.  
  1489. on: anInteractor
  1490.     ^self new addChild: ("MessageLogger on:" anInteractor "excluding: #(interactorAt:)")! !
  1491.  
  1492. Interactor subclass: #StemInteractor
  1493.     instanceVariableNames: 'parent origin preferredExtent hStretch vStretch '
  1494.     classVariableNames: ''
  1495.     poolDictionaries: ''
  1496.     category: 'Interactors-Framework'!
  1497. StemInteractor comment:
  1498. 'parent                (Representation) the composite representation of which I am part
  1499. topInteractor        (Interactor) the root of the interactor hierarchy of which I am part
  1500. origin                (Point) my origin in window-relative coordinates
  1501. preferredExtent    (Point) my default (usually smallest) size
  1502.  
  1503. [v|h]Stretch            (Boolean) true if I wish to stay my default size, false if I can be stretched.
  1504.                     One each for horizontal and vertical directions. This may be extended in
  1505.                     future to allow a "stretchiness" value rather than just a binary flag.'!
  1506.  
  1507.  
  1508. !StemInteractor methodsFor: 'initialize-release'!
  1509.  
  1510. initialize
  1511.     super initialize.
  1512.     origin := 0@0.
  1513.     vStretch := hStretch := true!
  1514.  
  1515. release
  1516.     parent := nil.
  1517.     super release! !
  1518.  
  1519. !StemInteractor methodsFor: 'accessing-geometry'!
  1520.  
  1521. bounds
  1522.     ^self origin extent: self extent!
  1523.  
  1524. bounds: bBox
  1525.     bBox extent >= self minimumExtent ifFalse: [self error: 'attempt to set bounds smaller than minimum'].
  1526.     self
  1527.         origin: bBox origin;
  1528.         extent: bBox extent.
  1529.     ^bBox!
  1530.  
  1531. corner
  1532.     ^self origin + self extent!
  1533.  
  1534. minimumExtent
  1535.     ^preferredExtent isNil
  1536.         ifTrue: [Point zero]
  1537.         ifFalse: [preferredExtent copy]!
  1538.  
  1539. minimumExtent: e
  1540.     preferredExtent := e!
  1541.  
  1542. origin
  1543.     ^origin!
  1544.  
  1545. origin: aPoint
  1546.     origin := aPoint!
  1547.  
  1548. preferredExtent: e
  1549.     ^preferredExtent := e max: self minimumExtent!
  1550.  
  1551. preferredHeight
  1552.     ^self minimumExtent y!
  1553.  
  1554. preferredWidth
  1555.     ^self minimumExtent x! !
  1556.  
  1557. !StemInteractor methodsFor: 'accessing-elasticity'!
  1558.  
  1559. elastic: r
  1560.     self hElastic: r; vElastic: r!
  1561.  
  1562. hElastic
  1563.     ^hStretch!
  1564.  
  1565. hElastic: f
  1566.     hStretch := f!
  1567.  
  1568. hRigid
  1569.     ^hStretch not!
  1570.  
  1571. hRigid: f
  1572.     hStretch := f not!
  1573.  
  1574. rigid
  1575.     self rigid: true!
  1576.  
  1577. rigid: r
  1578.     self hRigid: r; vRigid: r!
  1579.  
  1580. vElastic
  1581.     ^vStretch!
  1582.  
  1583. vElastic: f
  1584.     vStretch := f!
  1585.  
  1586. vRigid
  1587.     ^vStretch not!
  1588.  
  1589. vRigid: f
  1590.     vStretch := f not! !
  1591.  
  1592. !StemInteractor methodsFor: 'accessing'!
  1593.  
  1594. addChild: aChild beforeClass: aClass
  1595.     "overridden for composites of all flavors..."
  1596.  
  1597.     ^self addChild: aChild!
  1598.  
  1599. parent
  1600.     ^parent!
  1601.  
  1602. parent: p
  1603.     parent := p!
  1604.  
  1605. transparentParent
  1606.     ^parent! !
  1607.  
  1608. !StemInteractor methodsFor: 'event support'!
  1609.  
  1610. selectButtonPressed
  1611.     "The select button is considered released if either the redButton is inactive or the cursor is outside the receiver's bounds"
  1612.  
  1613.     ^self sensor redButtonPressed and: [self bounds containsPoint: self sensor cursorPoint]! !
  1614.  
  1615. !StemInteractor methodsFor: 'testing'!
  1616.  
  1617. hasIndirectParent: anInteractor
  1618.     ^anInteractor == self or: [self parent hasIndirectParent: anInteractor]! !
  1619.  
  1620. StemInteractor subclass: #SliderInteractor
  1621.     instanceVariableNames: 'valueBlock minVal maxVal ticks currentValue sliderBounds valueBounds incrementSize '
  1622.     classVariableNames: 'DefaultIncrement '
  1623.     poolDictionaries: ''
  1624.     category: 'Interactors-Framework'!
  1625.  
  1626.  
  1627. !SliderInteractor methodsFor: 'initialize-release'!
  1628.  
  1629. initialize
  1630.     self
  1631.         valueBlock: [ :i :x ];
  1632.         minVal: 0;
  1633.         maxVal: 100;
  1634.         ticks: 10;
  1635.         incrementSize: self defaultIncrement.
  1636.     super initialize! !
  1637.  
  1638. !SliderInteractor methodsFor: 'geometry'!
  1639.  
  1640. computeBounds: b
  1641.     | vbox |
  1642.     vbox := self maxVal printString asComposedText bounds.
  1643.     vbox := vbox translatedBy: b origin.
  1644.     self sliderBounds: ((vbox topRight + (self edgeSpace@0) corner: b corner) insetBy: self edgeSpace).
  1645.     self valueBounds: (vbox translatedBy: (self edgeSpace - 1)@(b extent y - vbox height) // 2).
  1646.     ^self bounds: b!
  1647.  
  1648. computeExtent
  1649.     ^self preferredExtent: 200@20! !
  1650.  
  1651. !SliderInteractor methodsFor: 'accessing'!
  1652.  
  1653. clearValue
  1654.     self currentValue: nil; render.
  1655.     self valueBlock value: self value: nil!
  1656.  
  1657. currentOrMaxValue
  1658.     ^self currentValue isNil ifTrue: [self maxVal] ifFalse: [self currentValue]!
  1659.  
  1660. currentOrMinValue
  1661.     ^self currentValue isNil ifTrue: [self minVal] ifFalse: [self currentValue]!
  1662.  
  1663. currentValue
  1664.     ^currentValue!
  1665.  
  1666. currentValue: aNumber
  1667.     currentValue := aNumber isNil ifFalse: [self constrain: aNumber]!
  1668.  
  1669. decrement
  1670.     self decrement: self incrementSize!
  1671.  
  1672. decrement: aNumber
  1673.     
  1674.     self newValue: self currentOrMaxValue - aNumber!
  1675.  
  1676. defaultIncrement
  1677.     ^DefaultIncrement!
  1678.  
  1679. increment
  1680.     self increment: self incrementSize!
  1681.  
  1682. increment: aNumber
  1683.     self newValue: self currentOrMinValue + aNumber!
  1684.  
  1685. incrementSize
  1686.     ^incrementSize!
  1687.  
  1688. incrementSize: aNumber
  1689.     incrementSize := aNumber!
  1690.  
  1691. maxVal
  1692.     ^maxVal!
  1693.  
  1694. maxVal: aNumber
  1695.     maxVal := aNumber!
  1696.  
  1697. minVal
  1698.     ^minVal!
  1699.  
  1700. minVal: aNumber
  1701.     minVal := aNumber!
  1702.  
  1703. newValue: aNumber
  1704.  
  1705.     | gc newVal |
  1706.     newVal := self constrain: aNumber.
  1707.     self currentValue = newVal
  1708.         ifFalse:
  1709.             [gc := self graphicsContext.
  1710.             (self
  1711.                 invalidateSliderOn: gc;
  1712.                 currentValue: newVal;
  1713.                 renderSliderOn: gc;
  1714.                 renderValueOn: gc;
  1715.                 valueBlock) value: self value: currentValue]!
  1716.  
  1717. sliderBounds
  1718.     ^sliderBounds!
  1719.  
  1720. sliderBounds: bb
  1721.     sliderBounds := bb!
  1722.  
  1723. ticks
  1724.     ^ticks!
  1725.  
  1726. ticks: anInteger
  1727.     "0 turns the ticking off"
  1728.  
  1729.     ticks := anInteger!
  1730.  
  1731. valueBlock
  1732.     ^valueBlock!
  1733.  
  1734. valueBlock: vb
  1735.     valueBlock := vb!
  1736.  
  1737. valueBounds
  1738.     ^valueBounds!
  1739.  
  1740. valueBounds: bb
  1741.     valueBounds := bb! !
  1742.  
  1743. !SliderInteractor methodsFor: 'rendering'!
  1744.  
  1745. renderForegroundOn: aGC
  1746.  
  1747.     self
  1748.         renderSliderOn: aGC;
  1749.         renderValueOn: aGC! !
  1750.  
  1751. !SliderInteractor methodsFor: 'event response'!
  1752.  
  1753. keyboardDown
  1754.  
  1755.     [self sensor keyboardPressed]    
  1756.         whileTrue: [self processChar: self sensor keyboardEvent keyValue]!
  1757.  
  1758. selectDown
  1759.  
  1760.     (self bounds containsPoint: self sensor cursorPoint)
  1761.         ifTrue: [self trackButton]!
  1762.  
  1763. trackButton
  1764.  
  1765.     [self sensor redButtonPressed]
  1766.         whileTrue:
  1767.             [self newValue: (self sensor cursorPoint x - self sliderBounds left
  1768.                                 / self sliderBounds width
  1769.                                 * (self maxVal - self minVal) + self minVal)]! !
  1770.  
  1771. !SliderInteractor methodsFor: 'keyboard processing'!
  1772.  
  1773. processChar: char
  1774.  
  1775.     char isDigit
  1776.         ifTrue: [self processDigit: char asInteger - $0 asInteger]
  1777.         ifFalse: [char asInteger == 127 ifTrue: [self processDelete]]!
  1778.  
  1779. processDelete
  1780.     self currentValue notNil
  1781.         ifTrue:
  1782.             [self currentValue < 10
  1783.                 ifTrue: [self clearValue]
  1784.                 ifFalse: [ | newVal |
  1785.                     newVal := self currentValue // 10.
  1786.                     newVal < self minVal
  1787.                         ifTrue: [self clearValue]
  1788.                         ifFalse: [self newValue: newVal]]]!
  1789.  
  1790. processDigit: num
  1791.  
  1792.     | newVal |
  1793.     newVal := self currentValue isNil
  1794.         ifTrue: [num]
  1795.         ifFalse: [self currentValue * 10 + num].
  1796.     self newValue: newVal! !
  1797.  
  1798. !SliderInteractor methodsFor: 'look and feel'!
  1799.  
  1800. edgeSpace
  1801.     "an ABSOLUTE number of pixels"
  1802.     ^5!
  1803.  
  1804. lineWidth
  1805.     ^1!
  1806.  
  1807. minorHeight
  1808.     "a FACTOR of minor:major ticks"
  1809.     ^0.8!
  1810.  
  1811. sliderHeight
  1812.     "a FACTOR of slider:window height"
  1813.     ^0.8!
  1814.  
  1815. sliderWidth
  1816.     "an ABSOLUTE slider width in pixels"
  1817.     ^3! !
  1818.  
  1819. !SliderInteractor methodsFor: 'private-geometry'!
  1820.  
  1821. maxValText
  1822.     ^self maxVal printString asComposedText! !
  1823.  
  1824. !SliderInteractor methodsFor: 'private-rendering'!
  1825.  
  1826. buttonBounds
  1827.  
  1828.     | sliderx slidery |
  1829.     sliderx := self currentValue - self minVal / (self maxVal - self minVal) * self sliderBounds width + self sliderBounds origin x.
  1830.     slidery := (self sliderBounds height / 2 * self sliderHeight) asInteger.
  1831.     ^((sliderx - (self sliderWidth // 2))@(self sliderBounds center y - slidery) extent: (self sliderWidth@(slidery * 2)))!
  1832.  
  1833. invalidateSliderOn: aGC
  1834.  
  1835.     | paint |
  1836.     self currentValue notNil
  1837.         ifTrue:
  1838.             [paint := aGC paint.
  1839.             aGC
  1840.                 paint: aGC medium background;
  1841.                 displayRectangle: self buttonBounds;
  1842.                 paint: paint]!
  1843.  
  1844. renderSliderOn: aGC
  1845.  
  1846.     | midline left right major minor bbox |
  1847.     bbox := self sliderBounds.
  1848.     left := bbox left.
  1849.     right := bbox right.
  1850.     major := bbox height // 2.
  1851.     minor := (major * self minorHeight) asInteger.
  1852.     midline := bbox center y.
  1853.     aGC
  1854.         lineWidth: self lineWidth * 2;
  1855.         displayLineFrom: left@(midline - major) to: left@(midline + major);
  1856.         displayLineFrom: right@(midline - major) to: right@(midline + major);
  1857.         lineWidth: self lineWidth;
  1858.         displayLineFrom: left@midline to: right@midline.
  1859.     ticks > 0 ifTrue: [ | gap |
  1860.         gap := bbox width / self ticks.
  1861.         1 to: self ticks do: [ :x | aGC displayLineFrom: (x * gap + left)@(midline - minor) to: (x * gap + left)@(midline)]].
  1862.  
  1863.     self currentValue notNil ifTrue: [aGC displayRectangle: self buttonBounds]!
  1864.  
  1865. renderValueOn: aGC
  1866.  
  1867.     | paint visual |
  1868.     visual := (self currentValue isNil ifTrue: ['?'] ifFalse: [self currentValue printString]) asComposedText.
  1869.     paint := aGC paint.
  1870.     aGC
  1871.         paint: aGC medium background;
  1872.         displayRectangle: self valueBounds;
  1873.         paint: paint;
  1874.         display: visual
  1875.             at: (self valueBounds origin translatedBy: self valueBounds extent - visual extent // 2)! !
  1876.  
  1877. !SliderInteractor methodsFor: 'printing'!
  1878.  
  1879. printHierarchyOn: aStream indent: i
  1880.     aStream crtab: i; nextPutAll: self class name , self auxiliaryPrintInfo! !
  1881.  
  1882. !SliderInteractor methodsFor: 'private'!
  1883.  
  1884. constrain: aNumber
  1885.     ^(aNumber asInteger max: self minVal) min: self maxVal! !
  1886. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1887.  
  1888. SliderInteractor class
  1889.     instanceVariableNames: ''!
  1890.  
  1891.  
  1892. !SliderInteractor class methodsFor: 'class initialization'!
  1893.  
  1894. initialize
  1895.     DefaultIncrement := 1! !
  1896.  
  1897. SliderInteractor subclass: #FixedPointSliderInteractor
  1898.     instanceVariableNames: 'scaling '
  1899.     classVariableNames: ''
  1900.     poolDictionaries: ''
  1901.     category: 'Interactors-Framework'!
  1902.  
  1903.  
  1904. !FixedPointSliderInteractor methodsFor: 'initialize-release'!
  1905.  
  1906. initialize
  1907.     super initialize.
  1908.     self scaling: 10! !
  1909.  
  1910. !FixedPointSliderInteractor methodsFor: 'geometry'!
  1911.  
  1912. computeBounds: b
  1913.     | vbox |
  1914.     vbox := ((self maxVal * self scaling) printString , '.') asComposedText bounds.
  1915.     vbox := vbox translatedBy: b origin.
  1916.     self sliderBounds: ((vbox topRight + (self edgeSpace@0) corner: b corner) insetBy: self edgeSpace).
  1917.     self valueBounds: (vbox translatedBy: (self edgeSpace - 1)@(b extent y - vbox height) // 2).
  1918.     ^self bounds: b! !
  1919.  
  1920. !FixedPointSliderInteractor methodsFor: 'accessing'!
  1921.  
  1922. scaling
  1923.     ^scaling!
  1924.  
  1925. scaling: aNumber
  1926.     scaling := aNumber! !
  1927.  
  1928. !FixedPointSliderInteractor methodsFor: 'private'!
  1929.  
  1930. constrain: aNumber
  1931.     ^((((aNumber max: self minVal) min: self maxVal) * self scaling) asInteger / self scaling) asFloat! !
  1932.  
  1933. StemInteractor subclass: #PrimitiveInteractor
  1934.     instanceVariableNames: 'component '
  1935.     classVariableNames: ''
  1936.     poolDictionaries: ''
  1937.     category: 'Interactors-Framework'!
  1938.  
  1939.  
  1940. !PrimitiveInteractor methodsFor: 'initialize-release'!
  1941.  
  1942. release
  1943.     self component release.
  1944.     self component: nil.
  1945.     super release! !
  1946.  
  1947. !PrimitiveInteractor methodsFor: 'accessing'!
  1948.  
  1949. addChild: c 
  1950.  
  1951.     self component isNil
  1952.         ifFalse: [self error: 'Duplicate interactor']
  1953.         ifTrue: [self component: c]! !
  1954.  
  1955. !PrimitiveInteractor methodsFor: 'private-accessing'!
  1956.  
  1957. component
  1958.     ^component!
  1959.  
  1960. component: brat
  1961.  
  1962.     component := brat!
  1963.  
  1964. transparentComponent
  1965.     ^component! !
  1966.  
  1967. !PrimitiveInteractor methodsFor: 'printing'!
  1968.  
  1969. printHierarchyOn: aStream indent: i
  1970.     aStream crtab: i; nextPutAll: self class name , self auxiliaryPrintInfo , ' on: ' , component printString! !
  1971. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1972.  
  1973. PrimitiveInteractor class
  1974.     instanceVariableNames: ''!
  1975.  
  1976.  
  1977. !PrimitiveInteractor class methodsFor: 'instance creation'!
  1978.  
  1979. addChild: aComponent
  1980.     ^self new addChild: aComponent!
  1981.  
  1982. on: aComponent
  1983.     "OBSOLETE -- VERY VERY NAUGHTY TO USE THIS!!"
  1984.  
  1985.     ^self new addChild: aComponent! !
  1986.  
  1987. PrimitiveInteractor subclass: #SimpleInteractor
  1988.     instanceVariableNames: 'justification '
  1989.     classVariableNames: ''
  1990.     poolDictionaries: ''
  1991.     category: 'Interactors-Framework'!
  1992.  
  1993.  
  1994. !SimpleInteractor methodsFor: 'initialize-release'!
  1995.  
  1996. initialize
  1997.     self justification: #center.
  1998.     ^super initialize! !
  1999.  
  2000. !SimpleInteractor methodsFor: 'geometry'!
  2001.  
  2002. computeBounds: bounds
  2003.     ^self bounds: bounds! !
  2004.  
  2005. !SimpleInteractor methodsFor: 'accessing'!
  2006.  
  2007. addChild: aThing
  2008.     self component: aThing!
  2009.  
  2010. justification
  2011.     ^justification!
  2012.  
  2013. justification: aSymbol
  2014.     justification := aSymbol! !
  2015.  
  2016. !SimpleInteractor methodsFor: 'rendering'!
  2017.  
  2018. renderForegroundOn: gc
  2019.  
  2020.     gc display: self component at: self justifiedOrigin! !
  2021.  
  2022. !SimpleInteractor methodsFor: 'private'!
  2023.  
  2024. justifiedOrigin
  2025.  
  2026.     | originX originY |
  2027.     originY := self origin y + ((self extent y - self component extent y) // 2).
  2028.     originX := (self justification == #left
  2029.         ifTrue: [self origin x] ifFalse: [self justification == #center
  2030.         ifTrue: [self origin x + ((self extent x - self component extent x) // 2)] ifFalse: [self justification == #right
  2031.         ifTrue: [self corner x - self component extent x] ifFalse: [self uimsError]]]).
  2032.     ^originX@originY! !
  2033.  
  2034. SimpleInteractor subclass: #ImageInteractor
  2035.     instanceVariableNames: ''
  2036.     classVariableNames: ''
  2037.     poolDictionaries: ''
  2038.     category: 'Interactors-Framework'!
  2039.  
  2040.  
  2041. !ImageInteractor methodsFor: 'geometry'!
  2042.  
  2043. computeExtent
  2044.  
  2045.     ^self preferredExtent: (self minimumExtent max: self component extent)! !
  2046.  
  2047. !ImageInteractor methodsFor: 'rendering'!
  2048.  
  2049. renderDeselectedOn: aGC
  2050.     self component depth == 1 ifTrue: [self component palette: MappedPalette whiteBlack].
  2051.     super renderDeselectedOn: aGC!
  2052.  
  2053. renderSelectedOn: aGC
  2054.     self component depth == 1 ifTrue: [self component palette: MappedPalette blackWhite].
  2055.     super renderSelectedOn: aGC! !
  2056.  
  2057. SimpleInteractor subclass: #TextInteractor
  2058.     instanceVariableNames: 'textConvertor '
  2059.     classVariableNames: ''
  2060.     poolDictionaries: ''
  2061.     category: 'Interactors-Framework'!
  2062.  
  2063.  
  2064. !TextInteractor methodsFor: 'geometry'!
  2065.  
  2066. computeBounds: bbox
  2067.     ^super computeBounds: bbox!
  2068.  
  2069. computeExtent
  2070.     ^self preferredExtent: (self minimumExtent max: (self component textStyle: (TextAttributes default)) extent)! !
  2071.  
  2072. !TextInteractor methodsFor: 'accessing'!
  2073.  
  2074. addChild: aTextOrString
  2075.  
  2076.     super addChild: aTextOrString asComposedText!
  2077.  
  2078. component
  2079.     ^self textConvertor isNil
  2080.         ifTrue: [super component]
  2081.         ifFalse: [(self textConvertor value: super component string) asComposedText]!
  2082.  
  2083. textConvertor
  2084.     ^textConvertor!
  2085.  
  2086. textConvertor: tc
  2087.     textConvertor := tc!
  2088.  
  2089. textStyle: ts! !
  2090.  
  2091. !TextInteractor methodsFor: 'rendering'!
  2092.  
  2093. graphicsContextFor: aComponent
  2094.  
  2095.     ^(super graphicsContextFor: aComponent) font: self font! !
  2096.  
  2097. !TextInteractor methodsFor: 'printing'!
  2098.  
  2099. printHierarchyOn: aStream indent: i
  2100.     aStream crtab: i; nextPutAll: self class name , self auxiliaryPrintInfo , ' on: ' , component string printString! !
  2101.  
  2102. TextInteractor subclass: #WrappedTextInteractor
  2103.     instanceVariableNames: ''
  2104.     classVariableNames: ''
  2105.     poolDictionaries: ''
  2106.     category: 'Interactors-Framework'!
  2107.  
  2108.  
  2109. !WrappedTextInteractor methodsFor: 'geometry'!
  2110.  
  2111. computeBounds: bbox
  2112.     self component compositionWidth: bbox width.
  2113.     ^super computeBounds: bbox!
  2114.  
  2115. computeExtent
  2116.     self minimumExtent x > 0 ifTrue: [self component compositionWidth: self minimumExtent x].
  2117.     ^super computeExtent! !
  2118.  
  2119. SimpleInteractor subclass: #ObjectInteractor
  2120.     instanceVariableNames: 'displayConvertor '
  2121.     classVariableNames: ''
  2122.     poolDictionaries: ''
  2123.     category: 'Interactors-Framework'!
  2124.  
  2125.  
  2126. !ObjectInteractor methodsFor: 'geometry'!
  2127.  
  2128. computeBounds: b
  2129.     ^self bounds: b!
  2130.  
  2131. computeExtent
  2132.     ^self preferredExtent: (self component extent max: self minimumExtent)! !
  2133.  
  2134. !ObjectInteractor methodsFor: 'accessing'!
  2135.  
  2136. component
  2137.     ^self displayConvertor isNil
  2138.         ifTrue: [super component]
  2139.         ifFalse: [(self displayConvertor value: super component) asComposedText]!
  2140.  
  2141. displayConvertor
  2142.     ^displayConvertor!
  2143.  
  2144. displayConvertor: aUnaryBlock
  2145.     displayConvertor := aUnaryBlock! !
  2146.  
  2147. PrimitiveInteractor subclass: #MVCInteractor
  2148.     instanceVariableNames: ''
  2149.     classVariableNames: ''
  2150.     poolDictionaries: ''
  2151.     category: 'Interactors-Framework'!
  2152.  
  2153.  
  2154. !MVCInteractor methodsFor: 'hierarchy'!
  2155.  
  2156. installHierarchy
  2157.  
  2158.     component container: self! !
  2159.  
  2160. !MVCInteractor methodsFor: 'geometry'!
  2161.  
  2162. computeBounds: bounds
  2163.  
  2164.     self bounds: bounds.
  2165.     self component bounds: bounds.
  2166.     ^self bounds!
  2167.  
  2168. computeExtent
  2169.     "Make an informed guess..."
  2170.  
  2171.     ^self preferredExtent: (ComposedText new lineGrid) asPoint! !
  2172.  
  2173. !MVCInteractor methodsFor: 'accessing'!
  2174.  
  2175. addChild: aThing
  2176.     self component: aThing! !
  2177.  
  2178. !MVCInteractor methodsFor: 'rendering'!
  2179.  
  2180. renderForegroundOn: aGC
  2181.     | rect |
  2182.     rect := self bounds.
  2183.     rect origin: rect origin + (1@1).
  2184.     rect corner: rect corner - self cornerCorrection.
  2185.     aGC
  2186.         paint: self backgroundColor;
  2187.         displayRectangle: rect;
  2188.         clippingRectangle: rect.
  2189.     self component displayOn: aGC at: self origin.
  2190.     aGC clippingRectangle: nil! !
  2191.  
  2192. !MVCInteractor methodsFor: 'event processing'!
  2193.  
  2194. selectDown
  2195.  
  2196.     self component startUp!
  2197.  
  2198. startUp
  2199.  
  2200.     "Pseudo-event sent periodically by the RootInteractor to let Interactors
  2201.     with multiple personalities (such as ourselves) a chance to start up the
  2202.     control loop in our underlying controller..."
  2203.  
  2204.     ^self component startUp! !
  2205.  
  2206. !MVCInteractor methodsFor: 'mvc messages'!
  2207.  
  2208. changedPreferredBounds: foo forComponent: bar!
  2209.  
  2210. compositionBoundsFor: anObject
  2211.  
  2212.     ^Point zero corner: self extent - self cornerCorrection!
  2213.  
  2214. edgeDecorationPolicy
  2215.  
  2216.     ^window edgeDecorationPolicy!
  2217.  
  2218. graphicsContextFor: anObject
  2219.  
  2220.     ^self graphicsContext
  2221.         translateBy: self origin;
  2222.         clippingRectangle: (self compositionBoundsFor: anObject)!
  2223.  
  2224. isOpen
  2225.     ^window isOpen!
  2226.  
  2227. localPointToGlobal: aPoint
  2228.  
  2229.     ^aPoint + self origin!
  2230.  
  2231. lookPreferences
  2232.  
  2233.     ^self window lookPreferences!
  2234.  
  2235. topComponent
  2236.  
  2237.     ^self window! !
  2238.  
  2239. MVCInteractor subclass: #InputFieldInteractor
  2240.     instanceVariableNames: 'acceptBlock '
  2241.     classVariableNames: ''
  2242.     poolDictionaries: ''
  2243.     category: 'Interactors-Framework'!
  2244.  
  2245.  
  2246. !InputFieldInteractor methodsFor: 'initialize-release'!
  2247.  
  2248. initialize
  2249.     super initialize.
  2250.     self addChild: (TextFieldView new initializeSelection)! !
  2251.  
  2252. !InputFieldInteractor methodsFor: 'accessing'!
  2253.  
  2254. acceptBlock
  2255.     ^acceptBlock!
  2256.  
  2257. acceptBlock: aBlock
  2258.     acceptBlock := aBlock!
  2259.  
  2260. addChild: sprog
  2261.     super addChild: sprog.
  2262.     sprog bounds: self bounds.
  2263.     sprog initializeSelection!
  2264.  
  2265. setText: aTextOrString
  2266.     self component
  2267.         deselect;
  2268.         editText: aTextOrString asText;
  2269.         initializeSelection;
  2270.         selectionIndex: aTextOrString size + 1! !
  2271.  
  2272. !InputFieldInteractor methodsFor: 'event response'!
  2273.  
  2274. accepted
  2275.     self acceptBlock value: self value: self component displayContents text string! !
  2276.  
  2277. StemInteractor subclass: #LinearInteractor
  2278.     instanceVariableNames: 'component '
  2279.     classVariableNames: ''
  2280.     poolDictionaries: ''
  2281.     category: 'Interactors-Framework'!
  2282.  
  2283.  
  2284. !LinearInteractor methodsFor: 'initialize-release'!
  2285.  
  2286. release
  2287.     self component release.
  2288.     self component: nil.
  2289.     super release! !
  2290.  
  2291. !LinearInteractor methodsFor: 'hierarchy'!
  2292.  
  2293. installComposites
  2294.     self component installComposites!
  2295.  
  2296. installHierarchy
  2297.  
  2298.     component parent: self.
  2299.     component installHierarchy.
  2300.     super installHierarchy.!
  2301.  
  2302. installSensor: aWin
  2303.  
  2304.     component installSensor: aWin.
  2305.     super installSensor: aWin!
  2306.  
  2307. installWindow: aWin
  2308.  
  2309.     component installWindow: aWin.
  2310.     super installWindow: aWin! !
  2311.  
  2312. !LinearInteractor methodsFor: 'accessing'!
  2313.  
  2314. addChild: c 
  2315.  
  2316.     self component isNil
  2317.         ifFalse: [self error: 'Duplicate interactor']
  2318.         ifTrue: [self component: c]!
  2319.  
  2320. component
  2321.     ^component!
  2322.  
  2323. component: brat
  2324.  
  2325.     component := brat!
  2326.  
  2327. installChild
  2328.  
  2329.     (self
  2330.         installHierarchy;
  2331.         installSensor: self sensor;
  2332.         installWindow: self window;
  2333.         computeExtent;
  2334.         computeBounds: self bounds;
  2335.         component) damaged.
  2336.     self render!
  2337.  
  2338. selected: flag
  2339.     super selected: flag.
  2340.     self component selected: flag!
  2341.  
  2342. transparentComponent
  2343.     ^component! !
  2344.  
  2345. !LinearInteractor methodsFor: 'default behavior'!
  2346.  
  2347. interactorAt: aPoint
  2348.  
  2349.     ^self component interactorAt: aPoint! !
  2350.  
  2351. !LinearInteractor methodsFor: 'rendering'!
  2352.  
  2353. renderOn: aGC
  2354.     super renderOn: aGC.
  2355.     self component renderOn: aGC! !
  2356.  
  2357. !LinearInteractor methodsFor: 'printing'!
  2358.  
  2359. printHierarchyOn: aStream indent: i
  2360.     aStream crtab: i; nextPutAll: self class name , self auxiliaryPrintInfo.
  2361.     self component printHierarchyOn: aStream indent: i+1! !
  2362. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2363.  
  2364. LinearInteractor class
  2365.     instanceVariableNames: ''!
  2366.  
  2367.  
  2368. !LinearInteractor class methodsFor: 'instance creation'!
  2369.  
  2370. addChild: aComponent
  2371.     ^self new addChild: aComponent!
  2372.  
  2373. on: aComponent
  2374.     ^self new addChild: aComponent! !
  2375.  
  2376. LinearInteractor subclass: #ScrollingInteractor
  2377.     instanceVariableNames: 'offset visibleExtent hScroller vScroller '
  2378.     classVariableNames: ''
  2379.     poolDictionaries: ''
  2380.     category: 'Interactors-Framework'!
  2381. ScrollingInteractor comment:
  2382. 'I wrap up an almost autonomous collection of interactors that can be scrolled arbitrarily, in any combination of horizontal and vertical directions. I cache the visual representation of my components so that they do not have to render themselves entirely onto my graphicsContext within some clipping rectangle every time they are scrolled.  There are obviously some updating issues to be addressed here, since updates into the localPixmap must also make it onto the enclosing pixmap.
  2383.  
  2384. component                (Interactor) the interactor which I scroll
  2385.  
  2386. offest                    (Point) the offset (due to scrolling) of my component
  2387.  
  2388. visibleExtent            (Point) the amout of the localPixmap (from the offset) that can be
  2389.                         seen (excludes the scrollbars)
  2390.  
  2391. localPixmap            (Pixmap) the cached visual representation of my component
  2392.  
  2393. localGraphicsContext    (GraphicsContext) a cached graphicsContext on the localPixmap
  2394.  
  2395. [h|v]Scroller                ([Horizontal | Vertical]Scrollbar) either the relevant type of scrollbar,
  2396.                         or nil for no scrollbar in that dimension
  2397.  
  2398. rendered                (Boolean) true if the component has already rendered itself on the localPixmap'!
  2399.  
  2400.  
  2401. !ScrollingInteractor methodsFor: 'initialize-release'!
  2402.  
  2403. initialize
  2404.     super initialize.
  2405.     self offset: 0@0!
  2406.  
  2407. useBothScrollers
  2408.  
  2409.     self useHorizontalScroller; useVerticalScroller!
  2410.  
  2411. useHorizontalScroller
  2412.  
  2413.     hScroller := HScroller new target: self!
  2414.  
  2415. useVerticalScroller
  2416.  
  2417.     vScroller := VScroller new target: self! !
  2418.  
  2419. !ScrollingInteractor methodsFor: 'hierarchy'!
  2420.  
  2421. installSensor: aSensor
  2422.  
  2423.     self sensor: aSensor.
  2424.     component installSensor: (ScrollerSensor new setWindow: window windowSensor: aSensor).
  2425.     component sensor globalOrigin: self origin + (self scrollerCorrection x @ 0).
  2426.     hScroller isNil ifFalse: [hScroller installSensor: aSensor].
  2427.     vScroller isNil ifFalse: [vScroller installSensor: aSensor].! !
  2428.  
  2429. !ScrollingInteractor methodsFor: 'accessing'!
  2430.  
  2431. hScroller
  2432.     ^hScroller!
  2433.  
  2434. hScroller: s
  2435.     hScroller := s!
  2436.  
  2437. offset
  2438.     ^offset!
  2439.  
  2440. offset: o
  2441.     offset := o!
  2442.  
  2443. visibleExtent
  2444.     ^visibleExtent!
  2445.  
  2446. visibleExtent: ve
  2447.     visibleExtent := ve!
  2448.  
  2449. vScroller
  2450.     ^vScroller!
  2451.  
  2452. vScroller: s
  2453.     vScroller := s! !
  2454.  
  2455. !ScrollingInteractor methodsFor: 'geometry'!
  2456.  
  2457. computeBounds: bounds
  2458.  
  2459.     | ve ce sc |
  2460.     self visibleExtent: (ve := bounds extent - (sc := self scrollerCorrection)).
  2461.     ce := self component minimumExtent.
  2462.     "(ve x < ce x or: [ve y < ce y]) ifTrue: [self uimsError]."
  2463.     self bounds: bounds.
  2464.     self component computeBounds: (0@0 extent:
  2465.             (self component hRigid ifTrue: [ce x] ifFalse: [ce x max: ve x]) @
  2466.             (self component vRigid ifTrue: [ce y] ifFalse: [ce y max: ve y])).
  2467.     self
  2468.         offset: 0@0;
  2469.         setRanges;
  2470.         setBars.
  2471.  
  2472.     vScroller notNil ifTrue: [vScroller bounds: (bounds origin corner: 1@-1 * sc + bounds bottomLeft + (0@1))]. "ASSUMES V-SCROLLERS ON THE LEFT!!!!!!"
  2473.  
  2474.     hScroller notNil ifTrue: [hScroller bounds: (1@-1 * sc + bounds bottomLeft - (1@0) corner: bounds corner)].
  2475.     ^self bounds!
  2476.  
  2477. computeExtent
  2478.     self component computeExtent.
  2479.     ^self minimumExtent max: 50@50! !
  2480.  
  2481. !ScrollingInteractor methodsFor: 'rendering'!
  2482.  
  2483. graphicsContextFor: aComponent
  2484.     | visibleOrigin |
  2485.     visibleOrigin := self scrollerCorrection x @ 0 + self origin.
  2486.     ^self graphicsContext
  2487.         clippingRectangle: (visibleOrigin extent: self visibleExtent);
  2488.         translateBy:  visibleOrigin - self offset!
  2489.  
  2490. renderInactiveRegionOn: gc
  2491.  
  2492.     (vScroller notNil and: [hScroller notNil])
  2493.         ifTrue: [gc
  2494.                 paint: self selectionBackgroundColor;
  2495.                 displayRectangle: (vScroller bounds bottomLeft corner: hScroller bounds bottomLeft)]!
  2496.  
  2497. renderOn: gc
  2498.  
  2499.     self component renderOn: (self graphicsContextFor: self component).
  2500.  
  2501.     vScroller notNil ifTrue: [vScroller renderOn: gc].
  2502.     hScroller notNil ifTrue: [hScroller renderOn: gc].
  2503.  
  2504.     self renderInactiveRegionOn: gc! !
  2505.  
  2506. !ScrollingInteractor methodsFor: 'private'!
  2507.  
  2508. scrollerCorrection
  2509.  
  2510.     ^((self vScroller notNil ifTrue: [vScroller width] ifFalse: [0])
  2511.     @(self hScroller notNil ifTrue: [hScroller height] ifFalse: [0]))!
  2512.  
  2513. setBars
  2514.     "set the size and position of the two scrollbars"
  2515.  
  2516.     vScroller isNil ifFalse: [vScroller
  2517.         min: offset y;
  2518.         max: offset y + self visibleExtent y].
  2519.     hScroller isNil ifFalse: [hScroller
  2520.         min: offset x;
  2521.         max: offset x + self visibleExtent x].!
  2522.  
  2523. setRanges
  2524.     "set the ranges of the two scrollbars"
  2525.  
  2526.     vScroller isNil ifFalse: [vScroller range: self component extent y].
  2527.     hScroller isNil ifFalse: [hScroller range: self component extent x]! !
  2528.  
  2529. !ScrollingInteractor methodsFor: 'scrolling'!
  2530.  
  2531. scrollBy: aPoint
  2532.  
  2533.     | newOffset corner componentExtent oldOffset |
  2534.     aPoint isZero
  2535.         ifFalse:
  2536.             [oldOffset := self offset.
  2537.             newOffset := aPoint * self warpFactor + self offset.
  2538.             corner := newOffset + self visibleExtent.
  2539.             componentExtent := self component extent.
  2540.             corner x > componentExtent x ifTrue: [corner x: componentExtent x].
  2541.             corner y > componentExtent y ifTrue: [corner y: componentExtent y].
  2542.             corner x < self visibleExtent x ifTrue: [corner x: self visibleExtent x].
  2543.             corner y < self visibleExtent y ifTrue: [corner y: self visibleExtent y].
  2544.             self offset: corner - self visibleExtent.
  2545.             self component sensor translateOrigin: oldOffset - self offset.
  2546.             self
  2547.                 renderOn: self parent graphicsContext;
  2548.                 setBars;
  2549.                 damaged]!
  2550.  
  2551. scrollDown
  2552.     self scrollBy: 0@1!
  2553.  
  2554. scrollLeft
  2555.     self scrollBy: -1@0!
  2556.  
  2557. scrollRight
  2558.     self scrollBy: 1@0!
  2559.  
  2560. scrollTo: aPoint
  2561.  
  2562.     | corner componentExtent oldOffset |
  2563.     oldOffset := self offset.
  2564.     corner := aPoint + self visibleExtent.
  2565.     componentExtent := self component extent.
  2566.     corner x > componentExtent x ifTrue: [corner x: componentExtent x].
  2567.     corner y > componentExtent y ifTrue: [corner y: componentExtent y].
  2568.     corner x < self visibleExtent x ifTrue: [corner x: self visibleExtent x].
  2569.     corner y < self visibleExtent y ifTrue: [corner y: self visibleExtent y].
  2570.     self offset: corner - self visibleExtent.
  2571.     self component sensor translateOrigin: oldOffset - self offset.
  2572.     self
  2573.         renderOn: self parent graphicsContext;
  2574.         setBars;
  2575.         damaged!
  2576.  
  2577. scrollUp
  2578.     self scrollBy: 0@-1!
  2579.  
  2580. warpFactor
  2581.     ^1! !
  2582.  
  2583. !ScrollingInteractor methodsFor: 'event enquiry'!
  2584.  
  2585. interactorAt: aPoint
  2586.  
  2587.     | correction visibleOrigin |
  2588.     hScroller isNil ifFalse:
  2589.         [(hScroller containsPoint: aPoint) ifTrue:
  2590.             [^hScroller interactorAt: aPoint]].
  2591.     vScroller isNil ifFalse:
  2592.         [(vScroller containsPoint: aPoint) ifTrue:
  2593.             [^vScroller interactorAt: aPoint]].
  2594.  
  2595.     "*** I AM ABOUT TO ASSUME THAT SCROLLBARS ARE AT LEFT AND AT BOTTOM ***"
  2596.  
  2597.     correction := self scrollerCorrection.
  2598.     visibleOrigin := self origin + (correction x @ 0).
  2599.     ((visibleOrigin extent: self visibleExtent) containsPoint: aPoint)
  2600.         ifTrue: [^self component interactorAt: aPoint - visibleOrigin + self offset].
  2601.     ^nil! !
  2602.  
  2603. ScrollingInteractor subclass: #CachedScrollingInteractor
  2604.     instanceVariableNames: 'localPixmap rendered localGraphicsContext '
  2605.     classVariableNames: ''
  2606.     poolDictionaries: ''
  2607.     category: 'Interactors-Framework'!
  2608.  
  2609.  
  2610. !CachedScrollingInteractor methodsFor: 'initialize-release'!
  2611.  
  2612. initialize
  2613.     super initialize.
  2614.     self rendered: false!
  2615.  
  2616. release
  2617.     self localPixmap release; close.
  2618.     super release! !
  2619.  
  2620. !CachedScrollingInteractor methodsFor: 'geometry'!
  2621.  
  2622. computeBounds: bounds
  2623.  
  2624.     | ve ce sc |
  2625.     self visibleExtent: (ve := bounds extent - (sc := self scrollerCorrection)).
  2626.     ce := self component minimumExtent.
  2627.     "(ve x < ce x or: [ve y < ce y]) ifTrue: [self uimsError]."
  2628.     self bounds: bounds.
  2629.     self component computeBounds: (0@0 extent:
  2630.             (self component hRigid ifTrue: [ce x] ifFalse: [ce x max: ve x]) @
  2631.             (self component vRigid ifTrue: [ce y] ifFalse: [ce y max: ve y])).
  2632.     self
  2633.         invalidateCachedCopy;
  2634.         offset: 0@0;
  2635.         setRanges;
  2636.         setBars.
  2637.  
  2638.     vScroller notNil ifTrue: [vScroller bounds: (bounds origin corner: 1@-1 * sc + bounds bottomLeft + (0@1))]. "ASSUMES V-SCROLLERS ON THE LEFT!!!!!!"
  2639.  
  2640.     hScroller notNil ifTrue: [hScroller bounds: (1@-1 * sc + bounds bottomLeft - (1@0) corner: bounds corner)].
  2641.     ^self bounds!
  2642.  
  2643. computeExtent
  2644.  
  2645.     | excess ext |
  2646.     ext := self component computeExtent.
  2647.     (self localPixmap isNil or: [(1@1 + ext <= self localPixmap extent) not])
  2648.         ifTrue: [self newPixmapExtent: 1@1 + ext].
  2649.     excess :=
  2650.         (self hScroller notNil ifTrue: [self hScroller minExtent] ifFalse: [Point zero]) +
  2651.         (self vScroller notNil ifTrue: [self vScroller minExtent] ifFalse: [Point zero]).
  2652.     ^(excess max: (self extent isNil
  2653.         ifTrue: [self preferredExtent: ext + self scrollerCorrection]
  2654.         ifFalse: [self extent])) max: 50@50! !
  2655.  
  2656. !CachedScrollingInteractor methodsFor: 'rendering'!
  2657.  
  2658. damaged
  2659.     self renderComponentOn: self parent graphicsContext.
  2660.     super damaged!
  2661.  
  2662. graphicsContext
  2663.     ^self localGraphicsContext!
  2664.  
  2665. graphicsContextFor: aComponent
  2666.     ^self localGraphicsContext!
  2667.  
  2668. reallyRenderComponentOn: gc
  2669.  
  2670.     gc
  2671.         clippingRectangle: ((self scrollerCorrection x @ 0 + self origin) extent: self visibleExtent);
  2672.         translateBy: self origin.
  2673.     self localPixmap
  2674.         displayOn: gc
  2675.         at: self offset negated + (self scrollerCorrection x @ 0).    "ASSUME H-SCROLLERS AT BOTTOM!!!!!!"
  2676.     gc
  2677.         translateBy: self origin negated;
  2678.         clippingRectangle: nil!
  2679.  
  2680. reallyRenderOn: gc
  2681.  
  2682.     self reallyRenderComponentOn: gc.
  2683.  
  2684.     vScroller notNil ifTrue: [vScroller renderOn: gc].
  2685.     hScroller notNil ifTrue: [hScroller renderOn: gc].
  2686.  
  2687.     self renderInactiveRegionOn: gc!
  2688.  
  2689. renderComponentOn: gc
  2690.  
  2691.     self rendered ifFalse: [self rendered: true; renderToCache].
  2692.     self reallyRenderComponentOn: gc!
  2693.  
  2694. renderOn: gc
  2695.  
  2696.     self rendered ifFalse: [self renderToCache; rendered: true].
  2697.     self reallyRenderOn: gc!
  2698.  
  2699. renderToCache
  2700.  
  2701.     self component renderOn: self localGraphicsContext! !
  2702.  
  2703. !CachedScrollingInteractor methodsFor: 'accessing'!
  2704.  
  2705. localGraphicsContext
  2706.     ^localGraphicsContext!
  2707.  
  2708. localGraphicsContext: gc
  2709.     localGraphicsContext := gc!
  2710.  
  2711. localPixmap
  2712.     ^localPixmap!
  2713.  
  2714. localPixmap: p
  2715.     localPixmap := p!
  2716.  
  2717. rendered
  2718.     ^rendered!
  2719.  
  2720. rendered: r
  2721.     rendered := r! !
  2722.  
  2723. !CachedScrollingInteractor methodsFor: 'private'!
  2724.  
  2725. clearLocalPixmap
  2726.  
  2727.     self localGraphicsContext medium
  2728.         background: self backgroundColor;
  2729.         clear!
  2730.  
  2731. invalidateCachedCopy
  2732.  
  2733.     | ext pext |
  2734.     ext := self visibleExtent max: self component extent.
  2735.     pext := self localPixmap extent.
  2736.     (ext x > pext x or: [ext y > pext y])
  2737.         ifTrue: [self newPixmapExtent: ext]
  2738.         ifFalse: [self clearLocalPixmap].
  2739.     self rendered: false!
  2740.  
  2741. newPixmapExtent: newExtent
  2742.  
  2743.     (self
  2744.         localPixmap: (Pixmap extent: newExtent);
  2745.         localGraphicsContext: (GraphicsContext on: self localPixmap);
  2746.         localGraphicsContext) font: FontDescription default.
  2747.     self clearLocalPixmap! !
  2748.  
  2749. LinearInteractor subclass: #TransparentInteractor
  2750.     instanceVariableNames: ''
  2751.     classVariableNames: ''
  2752.     poolDictionaries: ''
  2753.     category: 'Interactors-Framework'!
  2754.  
  2755.  
  2756. !TransparentInteractor methodsFor: 'transparent behavior'!
  2757.  
  2758. activate
  2759.     ^self component activate!
  2760.  
  2761. deactivate
  2762.     ^self component deactivate!
  2763.  
  2764. deselect
  2765.     ^self component deselect!
  2766.  
  2767. newSelection: anInteractorOrNil
  2768.     ^parent newSelection: anInteractorOrNil!
  2769.  
  2770. offBlock
  2771.     ^self component offBlock!
  2772.  
  2773. offBlock: aBlock
  2774.     self component offBlock: aBlock!
  2775.  
  2776. onBlock
  2777.     ^self component onBlock!
  2778.  
  2779. onBlock: aBlock
  2780.     self component onBlock: aBlock!
  2781.  
  2782. radioGroup: aGroupie
  2783.  
  2784.     self component radioGroup: aGroupie!
  2785.  
  2786. select
  2787.     ^self component select! !
  2788.  
  2789. !TransparentInteractor methodsFor: 'transparent accessing'!
  2790.  
  2791. addChild: anInteractor
  2792.  
  2793.     self component isNil
  2794.         ifTrue: [self component: anInteractor]
  2795.         ifFalse: [self component addChild: anInteractor]!
  2796.  
  2797. component
  2798.     ^component!
  2799.  
  2800. parent
  2801.     ^parent!
  2802.  
  2803. transparentComponent
  2804.     ^component transparentComponent!
  2805.  
  2806. transparentParent
  2807.     ^parent transparentParent!
  2808.  
  2809. transparentSelf
  2810.     ^self component transparentSelf! !
  2811.  
  2812. !TransparentInteractor methodsFor: 'transparent geometry'!
  2813.  
  2814. computeBounds: bounds
  2815.     self bounds: bounds.
  2816.     ^self component computeBounds: bounds!
  2817.  
  2818. computeExtent
  2819.  
  2820.     ^self preferredExtent: self component computeExtent!
  2821.  
  2822. hElastic
  2823.     ^self component hElastic!
  2824.  
  2825. hElastic: x
  2826.     self component hElastic: x!
  2827.  
  2828. hRigid
  2829.     ^self component hRigid!
  2830.  
  2831. hRigid: x
  2832.     self component hRigid: x!
  2833.  
  2834. vElastic
  2835.     ^self component vElastic!
  2836.  
  2837. vElastic: x
  2838.     self component vElastic: x!
  2839.  
  2840. vRigid
  2841.     ^self component vRigid!
  2842.  
  2843. vRigid: x
  2844.     self component vRigid: x! !
  2845.  
  2846. TransparentInteractor subclass: #InsetInteractor
  2847.     instanceVariableNames: 'inset '
  2848.     classVariableNames: 'DefaultInset '
  2849.     poolDictionaries: ''
  2850.     category: 'Interactors-Framework'!
  2851.  
  2852.  
  2853. !InsetInteractor methodsFor: 'initialize-release'!
  2854.  
  2855. initialize
  2856.     super initialize.
  2857.     self inset: self defaultInset! !
  2858.  
  2859. !InsetInteractor methodsFor: 'hierarchy'!
  2860.  
  2861. installHierarchy
  2862.  
  2863.     component
  2864.         parent: self;
  2865.         installHierarchy.!
  2866.  
  2867. installSensor: aSensor
  2868.  
  2869.     component installSensor: aSensor.
  2870.     super installSensor: aSensor!
  2871.  
  2872. installWindow: aWindow
  2873.  
  2874.     component installWindow: aWindow.
  2875.     super installWindow: aWindow! !
  2876.  
  2877. !InsetInteractor methodsFor: 'geometry'!
  2878.  
  2879. computeBounds: bounds
  2880.  
  2881.     self bounds: bounds.
  2882.     self component computeBounds: (bounds insetBy: self insetWidth).
  2883.     ^bounds!
  2884.  
  2885. computeExtent
  2886.  
  2887.     ^self preferredExtent: self component computeExtent + (self insetWidth * 2).! !
  2888.  
  2889. !InsetInteractor methodsFor: 'accessing'!
  2890.  
  2891. defaultInset
  2892.     ^DefaultInset!
  2893.  
  2894. inset
  2895.     "Overrides Interactor>>inset which wraps the receiver in an InsetInteractor
  2896.     with inset DefaultInset.  Thus multiple sends of inset add DefaultInset to the
  2897.     inset each time, but only ever cause at most a single InsetInteractor to created."
  2898.  
  2899.     self inset: self insetWidth + self defaultInset!
  2900.  
  2901. inset: i
  2902.     inset := i asInteger!
  2903.  
  2904. insetWidth
  2905.     ^inset! !
  2906. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2907.  
  2908. InsetInteractor class
  2909.     instanceVariableNames: ''!
  2910.  
  2911.  
  2912. !InsetInteractor class methodsFor: 'class initialization'!
  2913.  
  2914. initialize
  2915.     DefaultInset := 2! !
  2916.  
  2917. !InsetInteractor class methodsFor: 'instance creation'!
  2918.  
  2919. inset: i on: aComponent
  2920.     "This method now obsoleted by Interactor>>inset:"
  2921.  
  2922.     ^(self on: aComponent) inset: i! !
  2923.  
  2924. TransparentInteractor subclass: #BorderInteractor
  2925.     instanceVariableNames: 'foreground background selectionForeground selectionBackground borderWidth borderStyle '
  2926.     classVariableNames: 'DefaultBorderWidth '
  2927.     poolDictionaries: ''
  2928.     category: 'Interactors-Framework'!
  2929.  
  2930.  
  2931. !BorderInteractor methodsFor: 'initialize-release'!
  2932.  
  2933. initialize
  2934.     super initialize.
  2935.     self borderWidth: self defaultBorderWidth.
  2936.     self borderStyle: #square!
  2937.  
  2938. inverseBorders
  2939.     | fg bg sfg sbg |
  2940.     fg := self foregroundColor.
  2941.     bg := self backgroundColor.
  2942.     sfg := self selectionForegroundColor.
  2943.     sbg := self selectionBackgroundColor.
  2944.     self
  2945.         foreground: sfg;
  2946.         background: sbg;
  2947.         selectionForeground: fg;
  2948.         selectionBackground: bg!
  2949.  
  2950. recessedBorders
  2951.     | fg bg sfg sbg |
  2952.     fg := self foregroundColor.
  2953.     bg := self backgroundColor.
  2954.     sfg := self selectionForegroundColor.
  2955.     sbg := self selectionBackgroundColor.
  2956.     self
  2957.         foreground: bg;
  2958.         background: fg;
  2959.         selectionForeground: sbg;
  2960.         selectionBackground: sfg!
  2961.  
  2962. staticBorders
  2963.  
  2964.     self
  2965.         selectionForegroundColor: self foregroundColor;
  2966.         selectionBackgroundColor: self backgroundColor! !
  2967.  
  2968. !BorderInteractor methodsFor: 'geometry'!
  2969.  
  2970. computeBounds: bounds
  2971.  
  2972.     self bounds: bounds.
  2973.     self component computeBounds: (self borderStyle == #round
  2974.         ifTrue: [(bounds insetBy: bounds extent // 4)]
  2975.         ifFalse: [bounds insetBy: self borderWidth]).
  2976.     ^bounds!
  2977.  
  2978. computeExtent
  2979.  
  2980.     ^self preferredExtent: (self borderStyle == #round
  2981.             ifTrue: [self component computeExtent * 2]
  2982.             ifFalse: [self component computeExtent + (self borderWidth * 2)])! !
  2983.  
  2984. !BorderInteractor methodsFor: 'accessing'!
  2985.  
  2986. background: b
  2987.     background := b!
  2988.  
  2989. bordered
  2990.     self borderWidth: self borderWidth + self defaultBorderWidth!
  2991.  
  2992. borderStyle
  2993.     ^borderStyle!
  2994.  
  2995. borderStyle: bs
  2996.     borderStyle := bs!
  2997.  
  2998. borderWidth
  2999.     ^"self isSquare ifTrue: ["borderWidth"] ifFalse: [(self radius / 2) asInteger]"!
  3000.  
  3001. borderWidth: bw
  3002.     borderWidth := bw asInteger!
  3003.  
  3004. defaultBorderWidth
  3005.     ^DefaultBorderWidth!
  3006.  
  3007. extent: aPoint
  3008.     super extent: aPoint.
  3009.     self component extent: aPoint - (self borderWidth * 2)!
  3010.  
  3011. foreground: f
  3012.     foreground := f!
  3013.  
  3014. radius
  3015.     ^(self bounds height min: self bounds width) // 2!
  3016.  
  3017. roundBorders
  3018.     self borderStyle: #round!
  3019.  
  3020. selectionBackground: b
  3021.     selectionBackground := b!
  3022.  
  3023. selectionForeground: b
  3024.     selectionForeground := b!
  3025.  
  3026. squareBorders
  3027.     self borderStyle: #square! !
  3028.  
  3029. !BorderInteractor methodsFor: 'testing'!
  3030.  
  3031. isRound
  3032.     ^self borderStyle == #round!
  3033.  
  3034. isSquare
  3035.     ^self borderStyle == #square! !
  3036.  
  3037. !BorderInteractor methodsFor: 'rendering'!
  3038.  
  3039. renderBorderForeground: fg background: bg exterior: ex interior: in on: aGC
  3040.  
  3041.     self borderStyle == #square
  3042.         ifTrue: [self renderSquareBorderForeground: fg background: bg exterior: ex interior: in on: aGC]
  3043.         ifFalse: [    self borderStyle == #round
  3044.             ifTrue: [self renderRoundBorderForeground: fg background: bg exterior: ex interior: in on: aGC]
  3045.             ifFalse: [self error: 'buggered border, buddy - dunno how to draw "' , self borderStyle printString , '" borders!!']]!
  3046.  
  3047. renderDeselectedOn: aGC
  3048.  
  3049.     self
  3050.         renderBorderForeground: self foregroundColor
  3051.         background: self backgroundColor
  3052.         exterior: super backgroundColor
  3053.         interior: super backgroundColor
  3054.         on: aGC!
  3055.  
  3056. renderRoundBorderForeground: fg background: bg exterior: ex interior: in on: aGC
  3057.  
  3058.     | cbox bbox radius arcbox translation inset topLeft bottomRight |
  3059.     bbox := self bounds.
  3060.     cbox := self component bounds.
  3061.     radius := (cbox center y - bbox top min: cbox center x - bbox left) * 2.
  3062.     inset := radius / 2.
  3063.     arcbox := Point zero extent: radius.
  3064.     translation := 0@(bbox height - arcbox height / 2).
  3065.     topLeft := bbox origin + translation.
  3066.     bottomRight := bbox corner - translation.
  3067.     aGC
  3068.         lineWidth: self borderWidth;
  3069.         paint: ex;
  3070.         displayRectangle: bbox;
  3071.         paint: in;
  3072.         displayWedgeBoundedBy: arcbox startAngle: 90 sweepAngle: 180 at: topLeft;
  3073.         displayWedgeBoundedBy: arcbox startAngle: 270 sweepAngle: 180 at: bottomRight - radius;
  3074.         displayRectangle: (topLeft + (inset@0) corner: bottomRight - (inset@0));
  3075.         paint: bg;
  3076.         displayArcBoundedBy: arcbox startAngle: 135 sweepAngle: 135 at: topLeft;
  3077.         displayArcBoundedBy: arcbox startAngle: 270 sweepAngle: 45 at: bottomRight - radius;
  3078.         displayLineFrom: topLeft + (inset@0) to: bottomRight - radius + (inset@0);
  3079.         paint: fg;
  3080.         displayArcBoundedBy: arcbox startAngle: 315 sweepAngle: 135 at: bottomRight - radius;
  3081.         displayArcBoundedBy: arcbox startAngle: 90 sweepAngle: 45 at: topLeft;
  3082.         displayLineFrom: topLeft + radius - (inset@0) to: bottomRight - (inset@0)!
  3083.  
  3084. renderSelectedOn: aGC
  3085.  
  3086.     self
  3087.         renderBorderForeground: self selectionForegroundColor
  3088.         background: self selectionBackgroundColor
  3089.         exterior: super backgroundColor
  3090.         interior: super selectionBackgroundColor
  3091.         on: aGC!
  3092.  
  3093. renderSquareBorderForeground: fg background: bg exterior: ex interior: in on: aGC
  3094.  
  3095.     | bbox |
  3096.     bbox := self borderBounds.
  3097.     self borderWidth timesRepeat:
  3098.         [aGC
  3099.             paint: fg;
  3100.             displayPolyline: (OrderedCollection with: bbox bottomLeft with: bbox bottomRight with: bbox topRight);
  3101.             paint: bg;
  3102.             displayPolyline: (OrderedCollection with: bbox bottomLeft with: bbox topLeft with: bbox topRight).
  3103.         bbox origin: bbox origin + 1.
  3104.         bbox corner: bbox corner - 1]! !
  3105.  
  3106. !BorderInteractor methodsFor: 'coloring'!
  3107.  
  3108. backgroundColor
  3109.  
  3110.     ^background isNil ifTrue: [^super borderBackgroundColor] ifFalse: [^background]!
  3111.  
  3112. foregroundColor
  3113.  
  3114.     ^foreground isNil ifTrue: [^super borderForegroundColor] ifFalse: [^foreground]!
  3115.  
  3116. selectionBackgroundColor
  3117.  
  3118.     ^selectionBackground isNil ifTrue: [^super borderForegroundColor] ifFalse: [^selectionBackground]!
  3119.  
  3120. selectionForegroundColor
  3121.  
  3122.     ^selectionForeground isNil ifTrue: [^super borderBackgroundColor] ifFalse: [^selectionForeground]! !
  3123.  
  3124. !BorderInteractor methodsFor: 'event response'!
  3125.  
  3126. componentDeselected
  3127.  
  3128.     self selected: false; renderOn: self graphicsContext!
  3129.  
  3130. componentSelected
  3131.  
  3132.     self selected: true; renderOn: self graphicsContext! !
  3133.  
  3134. !BorderInteractor methodsFor: 'transparent geometry'!
  3135.  
  3136. minumumExtent: aPoint
  3137.  
  3138.     self component minimumExtent: aPoint - (self borderWidth * 2).
  3139.     super minimumExtent: aPoint! !
  3140. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3141.  
  3142. BorderInteractor class
  3143.     instanceVariableNames: ''!
  3144.  
  3145.  
  3146. !BorderInteractor class methodsFor: 'class initialization'!
  3147.  
  3148. initialize
  3149.     DefaultBorderWidth := 2! !
  3150.  
  3151. !BorderInteractor class methodsFor: 'instance creation'!
  3152.  
  3153. inverseOn: aComponent
  3154.     ^self on: aComponent; inverseBorders! !
  3155.  
  3156. TransparentInteractor subclass: #ActiveInteractor
  3157.     instanceVariableNames: 'onBlock offBlock radioGroup justification isToggle isCyclic isRepeating repeatPause repeatDelay '
  3158.     classVariableNames: 'RepeatDelay RepeatPause '
  3159.     poolDictionaries: ''
  3160.     category: 'Interactors-Framework'!
  3161.  
  3162.  
  3163. !ActiveInteractor methodsFor: 'initialize-release'!
  3164.  
  3165. initialize
  3166.     super initialize.
  3167.     self
  3168.         isToggle: false;
  3169.         isCyclic: false;
  3170.         isRepeating: false;
  3171.         repeatPause: self defaultRepeatPause;
  3172.         repeatDelay: self defaultRepeatDelay!
  3173.  
  3174. release
  3175.     self
  3176.         onBlock: nil;
  3177.         offBlock: nil;
  3178.         radioGroup: nil.
  3179.     super release! !
  3180.  
  3181. !ActiveInteractor methodsFor: 'accessing'!
  3182.  
  3183. addChild: aThing
  3184.     self component: aThing!
  3185.  
  3186. defaultRepeatDelay
  3187.     ^RepeatDelay!
  3188.  
  3189. defaultRepeatPause
  3190.     ^RepeatPause!
  3191.  
  3192. isCyclic
  3193.     ^isCyclic!
  3194.  
  3195. isCyclic: flag
  3196.     isCyclic := flag!
  3197.  
  3198. isRepeating
  3199.     ^isRepeating!
  3200.  
  3201. isRepeating: aBool
  3202.     isRepeating := aBool!
  3203.  
  3204. isToggle
  3205.     ^isToggle!
  3206.  
  3207. isToggle: t
  3208.     isToggle := t!
  3209.  
  3210. offBlock
  3211.     ^offBlock!
  3212.  
  3213. offBlock: aBlock
  3214.  
  3215.     offBlock := aBlock!
  3216.  
  3217. onBlock
  3218.     ^onBlock!
  3219.  
  3220. onBlock: aBlock
  3221.  
  3222.     onBlock := aBlock!
  3223.  
  3224. radioGroup
  3225.     ^radioGroup!
  3226.  
  3227. radioGroup: rg
  3228.     radioGroup := rg!
  3229.  
  3230. repeatDelay
  3231.     ^repeatDelay!
  3232.  
  3233. repeatDelay: anInteger
  3234.     repeatDelay := anInteger!
  3235.  
  3236. repeatPause
  3237.     ^repeatPause!
  3238.  
  3239. repeatPause: anInteger
  3240.     repeatPause := anInteger! !
  3241.  
  3242. !ActiveInteractor methodsFor: 'event enquiry'!
  3243.  
  3244. interactorAt: aPoint
  3245.     ^(self bounds containsPoint: aPoint) ifTrue: [self]! !
  3246.  
  3247. !ActiveInteractor methodsFor: 'event response'!
  3248.  
  3249. activate
  3250.     self onBlock value: self!
  3251.  
  3252. deactivate
  3253.     self offBlock notNil ifTrue: [self offBlock value: self]!
  3254.  
  3255. deselect
  3256.     self selected: false.
  3257.     self render!
  3258.  
  3259. select
  3260.     (self
  3261.         selected: true;
  3262.         renderOn: self graphicsContext;
  3263.         parent) componentSelected!
  3264.  
  3265. selectDown
  3266.  
  3267.     self selected isNil ifTrue: [self selected: false].
  3268.     (self selected and: [self isCyclic not])
  3269.         ifTrue:
  3270.             [(self
  3271.                 selected: false;
  3272.                 render; damaged;
  3273.                 offBlock) notNil ifTrue: [self offBlock value: self].
  3274.             self sensor waitNoButton]
  3275.         ifFalse:
  3276.             [self isRadioButton ifTrue: [self radioGroup newSelection: self].
  3277.             (self
  3278.                 selected: true;
  3279.                 render; damaged;
  3280.                 onBlock) notNil ifTrue: [self onBlock value: self].
  3281.             self isRepeating
  3282.                 ifTrue:
  3283.                     [ | ms |
  3284.                     ms := Time millisecondClockValue.
  3285.                     [self selectButtonPressed and: [Time millisecondClockValue - ms < self repeatPause]] whileTrue.
  3286.                     [self selectButtonPressed]
  3287.                         whileTrue:
  3288.                             [(self
  3289.                                 selected: false;
  3290.                                 render;
  3291.                                 damaged;
  3292.                                 offBlock) notNil ifTrue: [self onBlock value: self].
  3293.                             (self
  3294.                                 selected: true;
  3295.                                 render; damaged;
  3296.                                 onBlock) notNil ifTrue: [self onBlock value: self].
  3297.                             (Delay forMilliseconds: self repeatDelay) wait]]
  3298.                 ifFalse: [self sensor waitNoButton].
  3299.             (self isToggle or: [self isCyclic])
  3300.                 ifFalse:
  3301.                     [self selected: false.
  3302.                     self render; damaged.
  3303.                     self offBlock notNil ifTrue: [self offBlock value: self]].]! !
  3304.  
  3305. !ActiveInteractor methodsFor: 'controling'!
  3306.  
  3307. autoRepeat
  3308.     self isRepeating: true!
  3309.  
  3310. cyclic
  3311.     self isCyclic: true!
  3312.  
  3313. toggle
  3314.     self isToggle: true! !
  3315.  
  3316. !ActiveInteractor methodsFor: 'testing'!
  3317.  
  3318. isRadioButton
  3319.     ^self radioGroup notNil! !
  3320. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3321.  
  3322. ActiveInteractor class
  3323.     instanceVariableNames: ''!
  3324.  
  3325.  
  3326. !ActiveInteractor class methodsFor: 'class initialization'!
  3327.  
  3328. initialize
  3329.     RepeatPause := 500.
  3330.     RepeatDelay := 50! !
  3331.  
  3332. StemInteractor subclass: #ManifoldInteractor
  3333.     instanceVariableNames: 'children '
  3334.     classVariableNames: ''
  3335.     poolDictionaries: ''
  3336.     category: 'Interactors-Framework'!
  3337.  
  3338.  
  3339. !ManifoldInteractor methodsFor: 'initialize-release'!
  3340.  
  3341. release
  3342.     self children notNil ifTrue: [self children do: [ :sprog | sprog release]].
  3343.     self children: nil! !
  3344.  
  3345. !ManifoldInteractor methodsFor: 'hierarchy'!
  3346.  
  3347. installComposites
  3348.     self children do: [ :sprog | sprog installComposites]!
  3349.  
  3350. installHierarchy
  3351.  
  3352.     self children do: [ :sprog | sprog parent: self; installHierarchy]!
  3353.  
  3354. installSensor: aSensor
  3355.  
  3356.     self children do: [ :sprog | sprog installSensor: aSensor].
  3357.     super installSensor: aSensor!
  3358.  
  3359. installWindow: aWindow
  3360.  
  3361.     self children do: [ :sprog | sprog installWindow: aWindow].
  3362.     super installWindow: aWindow! !
  3363.  
  3364. !ManifoldInteractor methodsFor: 'accessing'!
  3365.  
  3366. addChild: aChild
  3367.     self children addLast: aChild!
  3368.  
  3369. children
  3370.     ^children!
  3371.  
  3372. children: brats
  3373.     children := brats!
  3374.  
  3375. moveChild: after toBeJustAfter: before
  3376.     children remove: after.
  3377.     children add: after after: before!
  3378.  
  3379. selected: flag
  3380.     children do: [ :brat | brat selected: flag].
  3381.     super selected: flag! !
  3382.  
  3383. !ManifoldInteractor methodsFor: 'printing'!
  3384.  
  3385. printHierarchyOn: aStream indent: i
  3386.  
  3387.     aStream crtab: i; nextPutAll: self class name , self auxiliaryPrintInfo.
  3388.     children do: [ :sprog | sprog printHierarchyOn: aStream indent: i+1]! !
  3389. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3390.  
  3391. ManifoldInteractor class
  3392.     instanceVariableNames: ''!
  3393.  
  3394.  
  3395. !ManifoldInteractor class methodsFor: 'instance creation'!
  3396.  
  3397. addChild: aComponent
  3398.     ^self new addChild: aComponent! !
  3399.  
  3400. ManifoldInteractor subclass: #VirtualInteractor
  3401.     instanceVariableNames: 'activeChild '
  3402.     classVariableNames: 'ShamDisplaySurface '
  3403.     poolDictionaries: ''
  3404.     category: 'Interactors-Framework'!
  3405.  
  3406.  
  3407. !VirtualInteractor methodsFor: 'geometry'!
  3408.  
  3409. computeBounds: bBox
  3410.  
  3411.     self bounds: bBox.
  3412.     self children do: [ :sprog | sprog computeBounds: bBox].
  3413.     ^self bounds!
  3414.  
  3415. computeExtent
  3416.  
  3417.     | width height |
  3418.     width := self extent x.
  3419.     height := self extent y.
  3420.     self children do: [ :sprog || ext |
  3421.         ext := sprog computeExtent.
  3422.         ext x > width ifTrue: [width := ext x].
  3423.         ext y > height ifTrue: [height := ext y]].
  3424.     ^self preferredExtent: width@height! !
  3425.  
  3426. !VirtualInteractor methodsFor: 'accessing'!
  3427.  
  3428. activeChild
  3429.     ^activeChild!
  3430.  
  3431. activeChild: brat
  3432.     activeChild := brat.
  3433.     brat notNil ifTrue: [brat parent: self; installHierarchy]!
  3434.  
  3435. addChild: anInteractor
  3436.  
  3437.     super addChild: anInteractor.
  3438.     self activeChild: anInteractor! !
  3439.  
  3440. !VirtualInteractor methodsFor: 'rendering'!
  3441.  
  3442. graphicsContextFor: anInteractor
  3443.  
  3444.     ^(anInteractor hasIndirectParent: self activeChild)
  3445.         ifTrue: [super graphicsContextFor: anInteractor]
  3446.         ifFalse: [GraphicsContext on: ShamDisplaySurface].
  3447.     "^super graphicsContextFor: anInteractor"!
  3448.  
  3449. renderOn: aGC
  3450.  
  3451.     super renderOn: aGC.
  3452.     self activeChild isNil
  3453.         ifFalse: [self activeChild renderOn: aGC]! !
  3454.  
  3455. !VirtualInteractor methodsFor: 'controlling'!
  3456.  
  3457. useComponentIndex: index
  3458.  
  3459.     self children size < index ifTrue: [self error: 'no such component in VirtualInteractor'].
  3460.     (self activeChild: (self children asArray at: index)) render!
  3461.  
  3462. useComponentNext
  3463.  
  3464.     | index |
  3465.     index := self children indexOf: self activeChild.
  3466.     index == self children size ifTrue: [index := 0].
  3467.     index := index + 1.
  3468.     (self activeChild: (self children asArray at: index)) render.
  3469.     ^self activeChild! !
  3470.  
  3471. !VirtualInteractor methodsFor: 'event enquiry'!
  3472.  
  3473. interactorAt: aPoint
  3474.  
  3475.     self activeChild isNil
  3476.         ifTrue: [^nil]
  3477.         ifFalse: [^self activeChild interactorAt: aPoint]! !
  3478. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3479.  
  3480. VirtualInteractor class
  3481.     instanceVariableNames: ''!
  3482.  
  3483.  
  3484. !VirtualInteractor class methodsFor: 'class initialization'!
  3485.  
  3486. initialize
  3487.  
  3488.     ShamDisplaySurface := Pixmap extent: 0@0! !
  3489.  
  3490. !VirtualInteractor class methodsFor: 'instance creation'!
  3491.  
  3492. new
  3493.     ^super new children: OrderedCollection new! !
  3494.  
  3495. ManifoldInteractor subclass: #GraphInteractor
  3496.     instanceVariableNames: 'actionBlocks activeRegions '
  3497.     classVariableNames: 'ActiveRegionSize AxisLabelOffset AxisResolution BottomSpace LeftSpace RightSpace TopSpace '
  3498.     poolDictionaries: ''
  3499.     category: 'Interactors-Framework'!
  3500.  
  3501.  
  3502. !GraphInteractor methodsFor: 'initialize-release'!
  3503.  
  3504. initialize
  3505.     super initialize.
  3506.     children := OrderedCollection new.
  3507.     actionBlocks := IdentityDictionary new.
  3508.     activeRegions := IdentityDictionary new! !
  3509.  
  3510. !GraphInteractor methodsFor: 'hierarchy'!
  3511.  
  3512. installComposites
  3513.     "override the one above that assumes children are interactors"!
  3514.  
  3515. installHierarchy!
  3516.  
  3517. installSensor: w
  3518.     "override the one above that assumes children are interactors"!
  3519.  
  3520. installWindow
  3521.     "override the one above that assumes children are interactors"!
  3522.  
  3523. installWindow: w
  3524.     "override the one above that assumes children are interactors"! !
  3525.  
  3526. !GraphInteractor methodsFor: 'geometry'!
  3527.  
  3528. computeBounds: bounds
  3529.     | maxVal minVal deltaVal verticalRange verticalScale deltaX baseLine abscissa |
  3530.     self bounds: bounds.
  3531.     maxVal := self maxVal.
  3532.     minVal := self minVal.
  3533.     deltaVal := maxVal - minVal.
  3534.     verticalRange := bounds height - self topSpace - self bottomSpace.
  3535.     verticalScale := verticalRange / deltaVal.
  3536.     deltaX := ((bounds width - self leftSpace - self rightSpace) / self children size).
  3537.     baseLine := bounds bottom - self bottomSpace.
  3538.     abscissa := bounds left + self leftSpace + (deltaX / 2).
  3539.     children do: [ :brat |
  3540.         self activeRegions at: brat put: (self activeRegionAt: abscissa@(baseLine - (brat value - minVal * verticalScale))).
  3541.         abscissa := abscissa + deltaX].
  3542.     ^bounds!
  3543.  
  3544. computeExtent
  3545.     ^self preferredExtent: 300@200! !
  3546.  
  3547. !GraphInteractor methodsFor: 'accessing'!
  3548.  
  3549. actionBlocks
  3550.     ^actionBlocks!
  3551.  
  3552. activeRegions
  3553.     ^activeRegions!
  3554.  
  3555. addChild: aValue
  3556.     children add: (IdentityWrapper on: aValue)!
  3557.  
  3558. addChild: aValue actionBlock: aBlockOrNil
  3559.     | id |
  3560.     self children add: (id := IdentityWrapper on: aValue).
  3561.     actionBlocks at: id put: aBlockOrNil.
  3562.     activeRegions at: id put: nil!
  3563.  
  3564. addChildren: bratList
  3565.  
  3566.     self children addAll: bratList!
  3567.  
  3568. children
  3569.     ^children!
  3570.  
  3571. children: c
  3572.     children := c! !
  3573.  
  3574. !GraphInteractor methodsFor: 'rendering'!
  3575.  
  3576. obsoleteRenderOn: aGC
  3577.  
  3578.     self
  3579.         renderBackgroundOn: aGC;
  3580.         renderCircularOn: aGC;        "use renderCircularOn: or renderRectangularOn: as appropriate!!"
  3581.         renderAxesOn: aGC!
  3582.  
  3583. renderAxesOn: aGC
  3584.  
  3585.     | vStep minVal floor ceiling vScale left right |
  3586.     vStep := self maxVal - (minVal := self minVal) / self axisResolution.
  3587.     floor := self bounds bottom - self bottomSpace.
  3588.     ceiling := self bounds top + self topSpace.
  3589.     vScale := floor - ceiling / self axisResolution.
  3590.     left := self bounds left + self leftSpace.
  3591.     right := self bounds right - self rightSpace.
  3592.     0 to: self axisResolution do: [ :yIndex || text |
  3593.         text := (yIndex * vStep + minVal) asInteger printString asComposedText.
  3594.          aGC
  3595.             displayLineFrom: left@(floor - (yIndex * vScale))
  3596.                 to: right@(floor - (yIndex * vScale));
  3597.             displayString: text asString
  3598.                 at: (left - text width - self axisLabelOffset)@(text height / 3 + floor - (yIndex * vScale))]!
  3599.  
  3600. renderCircularOn: aGC
  3601.  
  3602.     | vertices |
  3603.     vertices := (self children collect: [ :brat | aGC
  3604.         paint: self foregroundColor;
  3605.         displayWedgeBoundedBy: ((self activeRegions at: brat) insetBy: -1)
  3606.             startAngle: 0
  3607.             sweepAngle: 360;
  3608.         paint: self backgroundColor;
  3609.         displayWedgeBoundedBy: ((self activeRegions at: brat) insetBy: 1)
  3610.             startAngle: 0
  3611.             sweepAngle: 360.
  3612.         (self activeRegions at: brat) center]).
  3613.     aGC
  3614.         paint: self foregroundColor;
  3615.         displayPolyline: vertices!
  3616.  
  3617. renderRectangularOn: aGC
  3618.  
  3619.     | vertices |
  3620.     vertices := (self children collect: [ :brat | aGC
  3621.         paint: self foregroundColor;
  3622.         displayRectangle: (self activeRegions at: brat);
  3623.         paint: self backgroundColor;
  3624.         displayRectangle: ((self activeRegions at: brat) insetBy: 2).
  3625.         (self activeRegions at: brat) center]).
  3626.     aGC
  3627.         paint: self foregroundColor;
  3628.         displayPolyline: vertices! !
  3629.  
  3630. !GraphInteractor methodsFor: 'event response'!
  3631.  
  3632. selectDown
  3633.  
  3634.     | hotSpot activeBrat |
  3635.     hotSpot := self sensor cursorPoint.
  3636.     activeBrat := self children detect: [ :brat | (activeRegions at: brat) containsPoint: hotSpot] ifNone: [].
  3637.     activeBrat notNil ifTrue: [(actionBlocks at: activeBrat) value: activeBrat value]! !
  3638.  
  3639. !GraphInteractor methodsFor: 'constants'!
  3640.  
  3641. activeRegionSize
  3642.     ^ActiveRegionSize!
  3643.  
  3644. axisLabelOffset
  3645.     ^AxisLabelOffset!
  3646.  
  3647. axisResolution
  3648.     ^AxisResolution!
  3649.  
  3650. bottomSpace
  3651.     ^BottomSpace!
  3652.  
  3653. leftSpace
  3654.     ^LeftSpace!
  3655.  
  3656. rightSpace
  3657.     ^RightSpace!
  3658.  
  3659. topSpace
  3660.     ^TopSpace! !
  3661.  
  3662. !GraphInteractor methodsFor: 'private'!
  3663.  
  3664. activeRegionAt: aPoint
  3665.     ^(aPoint extent: self activeRegionSize asPoint) translatedBy: (self activeRegionSize / 2) negated!
  3666.  
  3667. maxVal
  3668.     ^self children inject: self children first value into: [ :max :brat | max max: brat value]!
  3669.  
  3670. minVal
  3671.     ^self children inject: self children first value into: [ :min :brat | min min: brat value]! !
  3672. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3673.  
  3674. GraphInteractor class
  3675.     instanceVariableNames: ''!
  3676.  
  3677.  
  3678. !GraphInteractor class methodsFor: 'class initialization'!
  3679.  
  3680. initialize
  3681.     self
  3682.         topSpace: 15;
  3683.         bottomSpace: 15;
  3684.         leftSpace: 30;
  3685.         rightSpace: 15;
  3686.         activeRegionSize: 9;
  3687.         axisResolution: 4;        "the number of y axis marks above the baseline"
  3688.         axisLabelOffset: 2        "the number of pixels to the left of the y axis marks to display the labels"! !
  3689.  
  3690. !GraphInteractor class methodsFor: 'accessing'!
  3691.  
  3692. activeRegionSize: anInteger
  3693.     ActiveRegionSize := anInteger!
  3694.  
  3695. axisLabelOffset: anInteger
  3696.     AxisLabelOffset := anInteger!
  3697.  
  3698. axisResolution: anInteger
  3699.     AxisResolution := anInteger!
  3700.  
  3701. bottomSpace: indent
  3702.     BottomSpace := indent!
  3703.  
  3704. leftSpace: indent
  3705.     LeftSpace := indent!
  3706.  
  3707. rightSpace: indent
  3708.     RightSpace := indent!
  3709.  
  3710. topSpace: indent
  3711.     TopSpace := indent! !
  3712.  
  3713. ManifoldInteractor subclass: #CompositeInteractor
  3714.     instanceVariableNames: 'isRadioGroup currentSelection '
  3715.     classVariableNames: 'FlattenPolicy '
  3716.     poolDictionaries: ''
  3717.     category: 'Interactors-Framework'!
  3718. CompositeInteractor comment:
  3719. 'children            (Set of Representation) representations which are part of me
  3720. '!
  3721.  
  3722.  
  3723. !CompositeInteractor methodsFor: 'initialize-release'!
  3724.  
  3725. initialize
  3726.     super initialize.
  3727.     self children: OrderedCollection new.
  3728.     self isRadioGroup: false!
  3729.  
  3730. initializeFrom: aComposite
  3731.     self
  3732.         isRadioGroup: aComposite isRadioGroup;
  3733.         currentSelection: aComposite currentSelection;
  3734.         children: aComposite children!
  3735.  
  3736. release
  3737.     children notNil ifTrue: [children do: [ :sprog | sprog release]].
  3738.     children := currentSelection := nil.
  3739.     super release! !
  3740.  
  3741. !CompositeInteractor methodsFor: 'hierarchy'!
  3742.  
  3743. assimilateChild: brat
  3744.     "brat is another composite"
  3745.  
  3746.     brat do: [ :bratlet | self add: bratlet after: brat].
  3747.     self remove: brat!
  3748.  
  3749. cloakChild: brat
  3750.     | index |
  3751.     index := self children indexOf: brat.
  3752.     self children at: index put: ((self children at: index) inset: 0)!
  3753.  
  3754. installComposites
  3755.  
  3756.     "This is a HORRENDOUS kludge to cope with pjc's interfaces.  His tortured interface
  3757.     generation stuff sometimes puts composites inside another composite which adds
  3758.     children in the same dimension (e.g. an AlignedRow inside another AlignedRow).
  3759.  
  3760.     This completely fucks the geometry calculations done by DynamicComposites, and
  3761.     should NOT be considered acceptable behavior for any interface generator.
  3762.  
  3763.     Two solutions are possible: either the incestuous children get wrapped in a cloaking
  3764.     device (such as an inset interactor with inset 0) or they become assimilated into
  3765.     the parent.  The policy used is determined by the class variable FlattenPolicy which
  3766.     can be #cloak (invisible inset) or #borg (assimilate into the whole).  The former trades
  3767.     an increase in space for time, the latter a decrease in space for time.  It is not yet
  3768.     clear whether these two policies ever produce different visual results.
  3769.  
  3770.     This gets propagated down the hierarchy BEFORE the RootInteractor kicks any
  3771.     geometry negotiations into motion."
  3772.  
  3773.     self children do: [ :sprog |
  3774.         (sprog isComposite and: [sprog dimension == self dimension])
  3775.             ifTrue: [self flattenPolicy == #cloak
  3776.                 ifTrue: [self cloakChild: sprog]
  3777.                 ifFalse: [self flattenPolicy == #borg
  3778.                     ifTrue: [^self assimilateChild:sprog; installComposites]
  3779.                     ifFalse: [self flattenPolicy == #none
  3780.                         ifTrue: [^self]
  3781.                         ifFalse: [self error: 'Rotten FlattenPolicy in CompositeInteractor!!']]]]].
  3782.     super installComposites.
  3783.     ((self children detect: [ :sprog | sprog isAlignedComposite] ifNone: []) notNil and: [self isDynamicComposite not])
  3784.         ifTrue: [self become: self asDynamicComposite]! !
  3785.  
  3786. !CompositeInteractor methodsFor: 'accessing'!
  3787.  
  3788. addChild: aChild
  3789.     super addChild: aChild.
  3790.     self isRadioGroup ifTrue: [aChild radioGroup: self]!
  3791.  
  3792. addChild: aChild at: aPosition
  3793.  
  3794.     "aPosition is either:
  3795.         #first        - prepend
  3796.         #last        - append
  3797.         anInteger    - absolute position:
  3798.             1    - first
  3799.             2    - second
  3800.             -1    - last
  3801.             -2    - next to last
  3802.     and so on..."
  3803.  
  3804.     | position |
  3805.     self isRadioGroup ifTrue: [aChild radioGroup: self].
  3806.     aPosition == #first ifTrue: [^self children addFirst: aChild].
  3807.     aPosition == #last ifTrue: [^self children addLast: aChild].
  3808.     (aPosition == 0 or: [self children size < aPosition abs]) ifTrue: [self uimsError].
  3809.     position := aPosition < 0
  3810.         ifTrue: [self children size + aPosition + 2]
  3811.         ifFalse: [aPosition].
  3812.     self addChild: aChild atIndex: aPosition.!
  3813.  
  3814. addChild: aChild atIndex: aPosition
  3815.  
  3816.     self isRadioGroup ifTrue: [aChild radioGroup: self].
  3817.     (aPosition == #first or: [aPosition == 0]) ifTrue: [^self children addFirst: aChild].
  3818.     aPosition == #last ifTrue: [^self children addLast: aChild].
  3819.     (aPosition == 0 or: [self children size < aPosition abs]) ifTrue: [self uimsError].
  3820.     self children add: aChild beforeIndex: (aPosition < 0
  3821.         ifTrue: [self children size + aPosition + 2]
  3822.         ifFalse: [aPosition])!
  3823.  
  3824. addChild: aChild beforeClass: aClass
  3825.  
  3826.     "add aChild before first instance of aClass (or a subclass thereof), otherwise at end"
  3827.  
  3828.     | target |
  3829.     target := self children detect: [ :sprog | sprog isMemberOf: aClass] ifNone: [].
  3830.     target isNil ifTrue: [^self children addLast: aChild].
  3831.     self children add: aChild before: target.
  3832.     self isRadioGroup ifTrue: [aChild radioGroup: self]!
  3833.  
  3834. beRadioGroup
  3835.     self isRadioGroup: true.
  3836.     self children do: [ :sprog | sprog radioGroup: self].
  3837.     self children do: [ :sprog | sprog selected ifTrue: [self currentSelection: sprog]]!
  3838.  
  3839. currentSelection
  3840.     ^currentSelection!
  3841.  
  3842. currentSelection: anInteractor
  3843.     currentSelection := anInteractor!
  3844.  
  3845. flattenPolicy
  3846.     ^FlattenPolicy!
  3847.  
  3848. installChild: aChild
  3849.     aChild computeExtent.
  3850.     self children addLast: aChild.
  3851.     self isRadioGroup ifTrue: [aChild radioGroup: self].
  3852.     aChild
  3853.         parent: self;
  3854.         installHierarchy;
  3855.         installSensor: self sensor;
  3856.         installWindow: self window.
  3857.     self computeBounds: self bounds.
  3858.     self renderOn: self graphicsContext!
  3859.  
  3860. isRadioGroup
  3861.     ^isRadioGroup!
  3862.  
  3863. isRadioGroup: flag
  3864.     isRadioGroup := flag!
  3865.  
  3866. radioGroup: aComposite
  3867.     self children do: [ :sprog | sprog radioGroup: aComposite]!
  3868.  
  3869. uninstallLastChild
  3870.     self children removeLast.
  3871.     self computeBounds: self bounds.
  3872.     self renderOn: self graphicsContext!
  3873.  
  3874. window: aWindow
  3875.     super window: aWindow.
  3876.     children do: [ :brat | brat window: aWindow]! !
  3877.  
  3878. !CompositeInteractor methodsFor: 'rendering'!
  3879.  
  3880. renderForegroundOn: gc
  3881.     self children isEmpty
  3882.         ifFalse: [self children do: [ :child | child renderOn: gc]]! !
  3883.  
  3884. !CompositeInteractor methodsFor: 'event enquiry'!
  3885.  
  3886. interactorAt: aPoint
  3887.  
  3888.     children do: [ :sprog |
  3889.         (sprog containsPoint: aPoint)
  3890.             ifTrue: [^sprog interactorAt: aPoint]].
  3891.     ^nil! !
  3892.  
  3893. !CompositeInteractor methodsFor: 'event response'!
  3894.  
  3895. newSelection: aChild
  3896.  
  3897.     (self currentSelection ~~ aChild and: [self currentSelection notNil])
  3898.         ifTrue:
  3899.             [self currentSelection
  3900.                 deactivate;
  3901.                 deselect.
  3902.             self damaged.].
  3903.     self currentSelection: aChild! !
  3904.  
  3905. !CompositeInteractor methodsFor: 'printing'!
  3906.  
  3907. printHierarchyOn: aStream indent: i
  3908.  
  3909.     aStream crtab: i; nextPutAll: self class name , self auxiliaryPrintInfo.
  3910.     children do: [ :sprog | sprog printHierarchyOn: aStream indent: i+1]! !
  3911.  
  3912. !CompositeInteractor methodsFor: 'testing'!
  3913.  
  3914. isComposite
  3915.     ^true! !
  3916. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3917.  
  3918. CompositeInteractor class
  3919.     instanceVariableNames: ''!
  3920.  
  3921.  
  3922. !CompositeInteractor class methodsFor: 'class initialization'!
  3923.  
  3924. initialize
  3925.     FlattenPolicy := #none! !
  3926.  
  3927. CompositeInteractor subclass: #ColumnInteractor
  3928.     instanceVariableNames: ''
  3929.     classVariableNames: ''
  3930.     poolDictionaries: ''
  3931.     category: 'Interactors-Framework'!
  3932.  
  3933.  
  3934. !ColumnInteractor methodsFor: 'geometry'!
  3935.  
  3936. computeBounds: bounds
  3937.  
  3938.     | currentOrigin elasticChildren lastElasticChild totalRigidHeight totalElasticHeight totalPreferredHeight spareHeight remainingSpareHeight |
  3939.  
  3940.     self bounds: bounds.
  3941.     elasticChildren := 0.
  3942.     self children size == 0 ifTrue: [^bounds].
  3943.     totalRigidHeight := totalElasticHeight := totalPreferredHeight := 0.
  3944.     children do: [ :child |
  3945.         child vRigid
  3946.             ifTrue: [totalRigidHeight := totalRigidHeight + child preferredHeight]
  3947.             ifFalse:
  3948.                 [totalElasticHeight := totalElasticHeight + child preferredHeight.
  3949.                 elasticChildren := elasticChildren + 1.
  3950.                 lastElasticChild := child]].
  3951.  
  3952.     totalPreferredHeight := totalElasticHeight + totalRigidHeight.
  3953.     (spareHeight := remainingSpareHeight := bounds height - totalPreferredHeight) < 0 ifTrue: [self uimsError].
  3954.     currentOrigin := bounds origin.
  3955.  
  3956.     children do: [ :child || cw ch |
  3957.         cw := child hRigid
  3958.                 ifTrue: [child preferredWidth]
  3959.                 ifFalse: [bounds width].
  3960.         child vRigid
  3961.             ifTrue: [ch := child preferredHeight]
  3962.             ifFalse: [child == lastElasticChild
  3963.                         ifTrue: [ch := child preferredHeight + remainingSpareHeight]
  3964.                         ifFalse: [
  3965.                             ch := (spareHeight * child preferredHeight / totalElasticHeight) asInteger.
  3966.                             remainingSpareHeight := remainingSpareHeight - ch.
  3967.                             ch := ch + child preferredHeight]].
  3968.         child computeBounds: (currentOrigin extent: cw@ch).
  3969.         currentOrigin := currentOrigin + (0@ch)].
  3970.  
  3971.     ^bounds!
  3972.  
  3973. computeExtent
  3974.  
  3975.     | width height |
  3976.     self hRigid: true.
  3977.     width := self extent x.
  3978.     height := 0.
  3979.     children do: [ :child || pb |
  3980.         pb := child computeExtent.
  3981.         height := height + pb y.
  3982.         pb x > width ifTrue: [width := pb x].
  3983.         self hRigid: (self hRigid and: [child hRigid])].
  3984.     ^self preferredExtent: width@height! !
  3985.  
  3986. !ColumnInteractor methodsFor: 'testing'!
  3987.  
  3988. dimension
  3989.     ^#vertical! !
  3990.  
  3991. !ColumnInteractor methodsFor: 'converting'!
  3992.  
  3993. asDynamicComposite
  3994.     ^DynamicColumnInteractor new initializeFrom: self! !
  3995.  
  3996. ColumnInteractor subclass: #DynamicColumnInteractor
  3997.     instanceVariableNames: ''
  3998.     classVariableNames: ''
  3999.     poolDictionaries: ''
  4000.     category: 'Interactors-Framework'!
  4001.  
  4002.  
  4003. !DynamicColumnInteractor methodsFor: 'geometry'!
  4004.  
  4005. computeExtent
  4006.     "Dynamically allocate field widths to children to line them up in rows or columns.
  4007.     If my children aren't all AlignedComposites then I'm buggered.
  4008.  
  4009.     This is only guaranteed to work if children have the same arity.  However,
  4010.     it won't break if this assumption is invalid - it'll just look real ugly."
  4011.  
  4012.     | width height leeways |
  4013.     leeways := Array
  4014.         new: (self children inject: 0 into: [ :max :brat | (brat isComposite ifTrue: [brat children size] ifFalse: [0]) max: max])
  4015.         withAll: 0.
  4016.     leeways size = 0 ifTrue: [^super computeExtent].
  4017.     self children do: [ :sprog |
  4018.         sprog isComposite
  4019.             ifTrue: [ | index |
  4020.                 index := 1.
  4021.                 sprog children do: [ :sproglet |
  4022.                     leeways at: index put: ((leeways at: index) max: sproglet computeExtent x).
  4023.                     index := index + 1]]].
  4024.     self children do: [ :sprog |
  4025.         sprog isAlignedComposite
  4026.             ifTrue: [| index |
  4027.                 index := 0.
  4028.                 sprog children do: [ :sproglet | sprog allocations at: sproglet put: (leeways at: (index := 1 + index))]]].
  4029.     self hRigid: true.
  4030.     width := height := 0.
  4031.     width := children inject: 0 into: [ :w :x | w max: (x computeExtent; preferredWidth)].
  4032.     children do: [ :child || box |
  4033.         height := height + (box := child computeExtent) y.
  4034.         self hRigid: (self hRigid and: [child hRigid])."
  4035.         child extent: width@box y.
  4036.         child isAlignedComposite
  4037.             ifTrue: [ | index |
  4038.                 index := 0.
  4039.                 child children do: [ :sprog | sprog extent: width@(leeways at: (index := index + 1))]]"].
  4040.     (width = 0 or: [height = 0]) ifTrue: [self uimsError].
  4041.     ^self preferredExtent: width@height! !
  4042.  
  4043. !DynamicColumnInteractor methodsFor: 'testing'!
  4044.  
  4045. dimension
  4046.     ^#vertical!
  4047.  
  4048. isDynamicComposite
  4049.     ^true! !
  4050.  
  4051. CompositeInteractor subclass: #AlignedCompositeInteractor
  4052.     instanceVariableNames: 'allocations '
  4053.     classVariableNames: ''
  4054.     poolDictionaries: ''
  4055.     category: 'Interactors-Framework'!
  4056.  
  4057.  
  4058. !AlignedCompositeInteractor methodsFor: 'initialize-release'!
  4059.  
  4060. initialize
  4061.     super initialize.    
  4062.     allocations := IdentityDictionary new! !
  4063.  
  4064. !AlignedCompositeInteractor methodsFor: 'hierarchy'!
  4065.  
  4066. assimilateChild: brat
  4067.     "brat is another composite"
  4068.  
  4069.     brat children do: [ :bratlet | self children add: bratlet after: brat].
  4070.     brat isAlignedComposite ifTrue: [self allocations addAll: brat allocations associations].
  4071.     self children remove: brat.
  4072.     self allocations removeKey: brat!
  4073.  
  4074. cloakChild: old
  4075.     | new |
  4076.     new := old inset: 0.
  4077.     self children at: (self children indexOf: old) put: new.
  4078.     self allocations
  4079.         at: new put: (self allocations at: old);
  4080.         removeKey: old! !
  4081.  
  4082. !AlignedCompositeInteractor methodsFor: 'accessing'!
  4083.  
  4084. addChild: anInteractor
  4085.     ^self addChild: anInteractor allocation: 1!
  4086.  
  4087. addChild: anInteractor allocation: anAllocation
  4088.     super addChild: anInteractor.
  4089.     self allocations at: anInteractor put: anAllocation!
  4090.  
  4091. addChild: anInteractor at: aPosition
  4092.     ^self addChild: anInteractor at: aPosition allocation: 1!
  4093.  
  4094. addChild: anInteractor at: aPosition allocation: anAllocation
  4095.  
  4096.     super addChild: anInteractor at: aPosition.
  4097.     self allocations at: anInteractor put: anAllocation!
  4098.  
  4099. addChild: anInteractor atIndex: anIndex
  4100.     ^self addChild: anInteractor atIndex: anIndex allocation: 1!
  4101.  
  4102. addChild: anInteractor atIndex: anIndex allocation: anAllocation
  4103.  
  4104.     super addChild: anInteractor atIndex: anIndex.
  4105.     self allocations at: anInteractor put: anAllocation!
  4106.  
  4107. addChild: aChild beforeClass: aClass
  4108.  
  4109.     ^self addChild: aChild beforeClass: aClass allocation: 1!
  4110.  
  4111. addChild: anInteractor beforeClass: aClass allocation: anAllocation
  4112.  
  4113.     super addChild: anInteractor beforeClass: aClass.
  4114.     self allocations at: anInteractor put: anAllocation!
  4115.  
  4116. allocations
  4117.     ^allocations!
  4118.  
  4119. installChild: aChild
  4120.  
  4121.     ^self error: 'not yet implemented - request assistance'!
  4122.  
  4123. moveChild: after toBeJustAfter: before
  4124.     ^self error: 'not yet implemented - request assistance!!'!
  4125.  
  4126. totalAllocation
  4127.  
  4128.     ^self allocations values inject: 0 into: [ :total :allocation | allocation + total]! !
  4129.  
  4130. !AlignedCompositeInteractor methodsFor: 'testing'!
  4131.  
  4132. isAlignedComposite
  4133.     ^true! !
  4134.  
  4135. AlignedCompositeInteractor subclass: #AlignedColumnInteractor
  4136.     instanceVariableNames: ''
  4137.     classVariableNames: ''
  4138.     poolDictionaries: ''
  4139.     category: 'Interactors-Framework'!
  4140.  
  4141.  
  4142. !AlignedColumnInteractor methodsFor: 'geometry'!
  4143.  
  4144. computeBounds: bounds
  4145.  
  4146.     | currentOrigin totalAllocation totalHeight sprogWidth |
  4147.     totalHeight := (self bounds: bounds) height.
  4148.     sprogWidth := bounds width.
  4149.     totalAllocation := self totalAllocation.
  4150.     currentOrigin := self origin.
  4151.     self children do: [ :sprog || sprogHeight |
  4152.         sprog == self children last
  4153.             ifTrue:
  4154.                 [sprog computeBounds: (currentOrigin corner: self bounds corner)]
  4155.             ifFalse:
  4156.                 [sprogHeight := ((self allocations at: sprog) / totalAllocation * totalHeight) asInteger.
  4157.                 sprogHeight < sprog minimumExtent y ifTrue: [self uimsError].
  4158.                 sprog computeBounds: (currentOrigin extent: sprogWidth@sprogHeight).
  4159.                 currentOrigin := currentOrigin + (0@sprogHeight)]].
  4160.     ^bounds!
  4161.  
  4162. computeExtent
  4163.  
  4164.     | width height totalAllocation |
  4165.  
  4166.     totalAllocation := self totalAllocation.
  4167.     self hRigid: true.
  4168.     width := height := 0.
  4169.     children do: [ :sprog || pb |
  4170.         pb := sprog computeExtent.
  4171.         height := height max: (totalAllocation / (allocations at: sprog) * pb y) asInteger + 1.
  4172.         width := pb x max: width.
  4173.         self hRigid: (self hRigid and: [sprog hRigid])].
  4174.     ^self preferredExtent: width@height!
  4175.  
  4176. computeMinimumExtent
  4177.     "Calculate my minimum extent, ignoring allocations"
  4178.  
  4179.     | width height |
  4180.     self hRigid: true.
  4181.     width := height := 0.
  4182.     children do: [ :sprog || pb |
  4183.         pb := sprog computeExtent.
  4184.         height := height + pb y.
  4185.         width := pb x max: width.
  4186.         self hRigid: (self hRigid and: [sprog hRigid])].
  4187.     ^self preferredExtent: width@height! !
  4188.  
  4189. !AlignedColumnInteractor methodsFor: 'testing'!
  4190.  
  4191. dimension
  4192.     ^#vertical! !
  4193.  
  4194. AlignedCompositeInteractor subclass: #AlignedRowInteractor
  4195.     instanceVariableNames: ''
  4196.     classVariableNames: ''
  4197.     poolDictionaries: ''
  4198.     category: 'Interactors-Framework'!
  4199.  
  4200.  
  4201. !AlignedRowInteractor methodsFor: 'geometry'!
  4202.  
  4203. computeBounds: bounds
  4204.  
  4205.     | currentOrigin totalAllocation totalWidth sprogHeight |
  4206.     totalWidth := (self bounds: bounds) width.
  4207.     sprogHeight := bounds height.
  4208.     totalAllocation := self totalAllocation.
  4209.     currentOrigin := self origin.
  4210.     self children do: [ :sprog || sprogWidth |
  4211.         sprog == self children last
  4212.             ifTrue:
  4213.                 [sprog computeBounds: (currentOrigin corner: self bounds corner)]
  4214.             ifFalse:
  4215.                 [sprogWidth := ((self allocations at: sprog) / totalAllocation * totalWidth) asInteger.
  4216.                 sprogWidth < sprog minimumExtent x ifTrue: [self uimsError].
  4217.                 sprog computeBounds: (currentOrigin extent: sprogWidth@sprogHeight).
  4218.                 currentOrigin := currentOrigin + (sprogWidth@0)]].
  4219.     ^bounds!
  4220.  
  4221. computeExtent
  4222.  
  4223.     | width height totalAllocation |
  4224.     totalAllocation := self totalAllocation.
  4225.     self vRigid: true.
  4226.     width := height := 0.
  4227.     children do: [ :sprog || pb |
  4228.         pb := sprog computeExtent.
  4229.         width := width max: (totalAllocation / (allocations at: sprog) * pb x) asInteger + 1.
  4230.         height := pb y max: height.
  4231.         self vRigid: (self vRigid and: [sprog vRigid])].
  4232.     ^self preferredExtent: width@height!
  4233.  
  4234. computeMinimumExtent
  4235.     "Calculate my minimum extent, ignoring allocations"
  4236.  
  4237.     | width height |
  4238.     self vRigid: true.
  4239.     width := height := 0.
  4240.     children do: [ :sprog || pb |
  4241.         pb := sprog computeExtent.
  4242.         width := width + pb x.
  4243.         height := pb y max: height.
  4244.         self vRigid: (self vRigid and: [sprog vRigid])].
  4245.     ^self preferredExtent: width@height! !
  4246.  
  4247. !AlignedRowInteractor methodsFor: 'testing'!
  4248.  
  4249. dimension
  4250.     ^#horizontal! !
  4251.  
  4252. CompositeInteractor subclass: #RowInteractor
  4253.     instanceVariableNames: ''
  4254.     classVariableNames: ''
  4255.     poolDictionaries: ''
  4256.     category: 'Interactors-Framework'!
  4257.  
  4258.  
  4259. !RowInteractor methodsFor: 'geometry'!
  4260.  
  4261. computeBounds: bounds
  4262.  
  4263.     | currentOrigin elasticChildren lastElasticChild totalRigidWidth totalElasticWidth totalPreferredWidth spareWidth remainingSpareWidth |
  4264.  
  4265.     self bounds: bounds.
  4266.     elasticChildren := 0.
  4267.     self children size == 0 ifTrue: [^bounds].
  4268.     totalRigidWidth := totalElasticWidth := totalPreferredWidth := 0.
  4269.     children do: [ :child |
  4270.         child hRigid
  4271.             ifTrue: [totalRigidWidth := totalRigidWidth + child preferredWidth]
  4272.             ifFalse:
  4273.                 [totalElasticWidth := totalElasticWidth + child preferredWidth.
  4274.                 elasticChildren := elasticChildren + 1.
  4275.                 lastElasticChild := child]].
  4276.  
  4277.     totalPreferredWidth := totalElasticWidth + totalRigidWidth.
  4278.     (spareWidth := remainingSpareWidth := bounds width - totalPreferredWidth) < 0 ifTrue: [self uimsError].
  4279.     currentOrigin := bounds origin.
  4280.  
  4281.     children do: [ :child || cw ch |
  4282.         ch := child vRigid
  4283.                 ifTrue: [child preferredHeight]
  4284.                 ifFalse: [bounds height].
  4285.         child hRigid
  4286.             ifTrue: [cw := child preferredWidth]
  4287.             ifFalse: [child == lastElasticChild
  4288.                         ifTrue: [cw := child preferredWidth + remainingSpareWidth]
  4289.                         ifFalse: [
  4290.                             cw := (spareWidth * child preferredWidth / totalElasticWidth) asInteger.
  4291.                             remainingSpareWidth := remainingSpareWidth - cw.
  4292.                             cw := cw + child preferredWidth]].
  4293.         child computeBounds: (currentOrigin extent: cw@ch).
  4294.         currentOrigin := currentOrigin + (cw@0)].
  4295.  
  4296.     ^bounds!
  4297.  
  4298. computeExtent
  4299.  
  4300.     | width height |
  4301.     self vRigid: true.
  4302.     width := 0.
  4303.     height := self extent y.
  4304.     children do: [ :child || pb |
  4305.         pb := child computeExtent.
  4306.         width := width + pb x.
  4307.         pb y > height ifTrue: [height := pb y].
  4308.         self vRigid: (self vRigid and: [child vRigid])].
  4309.     ^self preferredExtent: width@height! !
  4310.  
  4311. !RowInteractor methodsFor: 'testing'!
  4312.  
  4313. dimension
  4314.     ^#horizontal! !
  4315.  
  4316. !RowInteractor methodsFor: 'converting'!
  4317.  
  4318. asDynamicComposite
  4319.     ^DynamicRowInteractor new initializeFrom: self! !
  4320.  
  4321. RowInteractor subclass: #DynamicRowInteractor
  4322.     instanceVariableNames: ''
  4323.     classVariableNames: ''
  4324.     poolDictionaries: ''
  4325.     category: 'Interactors-Framework'!
  4326.  
  4327.  
  4328. !DynamicRowInteractor methodsFor: 'geometry'!
  4329.  
  4330. computeExtent
  4331.     "Dynamically allocate field widths to children to line them up in rows or columns.
  4332.     If my children aren't all AlignedComposites then I'm buggered.
  4333.  
  4334.     This is only guaranteed to work if children have the same arity.  However,
  4335.     it won't break if this assumption is invalid - it'll just look real ugly."
  4336.  
  4337.     | width height leeways |
  4338.     leeways := Array
  4339.         new: (self children inject: 0 into: [ :max :brat | (brat isComposite ifTrue: [brat children size] ifFalse: [0]) max: max])
  4340.         withAll: 0.
  4341.     self children do: [ :sprog |
  4342.         sprog isComposite
  4343.             ifTrue: [ | index |
  4344.                 index := 1.
  4345.                 sprog children do: [ :sproglet |
  4346.                     leeways at: index put: ((leeways at: index) max: sproglet computeExtent y).
  4347.                     index := index + 1]]].
  4348.     self children do: [ :sprog |
  4349.         sprog isAlignedComposite
  4350.             ifTrue: [| index |
  4351.                 index := 0.
  4352.                 sprog children do: [ :sproglet | sprog allocations at: sproglet put: (leeways at: (index := 1 + index))]]].
  4353.     self vRigid: true.
  4354.     width := 0.
  4355.     height := children inject: 0 into: [ :h :x | h max: (x computeExtent; preferredHeight)].
  4356.     children do: [ :child || box |
  4357.         width := width + (box := child computeExtent) x.
  4358.         self vRigid: (self vRigid and: [child vRigid])."
  4359.         child extent: box x@height.
  4360.         child isAlignedComposite
  4361.             ifTrue: [ | index |
  4362.                 index := 0.
  4363.                 child children do: [ :sprog | sprog extent: (leeways at: (index := index + 1))@height]]"].
  4364.     (width = 0 or: [height = 0]) ifTrue: [self uimsError].
  4365.     ^self preferredExtent: width@height! !
  4366.  
  4367. !DynamicRowInteractor methodsFor: 'testing'!
  4368.  
  4369. dimension
  4370.     ^#horizontal!
  4371.  
  4372. isDynamicComposite
  4373.     ^true! !
  4374.  
  4375. StemInteractor subclass: #FillerInteractor
  4376.     instanceVariableNames: ''
  4377.     classVariableNames: ''
  4378.     poolDictionaries: ''
  4379.     category: 'Interactors-Framework'!
  4380.  
  4381.  
  4382. !FillerInteractor methodsFor: 'hierarchy'!
  4383.  
  4384. installHierarchy
  4385.  
  4386.     "I don't have any children - so why should I care about parents?"
  4387.  
  4388.     "This message would not be necessary if children were installed
  4389.     correctly by their parents, rather than by an external agent."! !
  4390.  
  4391. !FillerInteractor methodsFor: 'geometry'!
  4392.  
  4393. computeBounds: bBox
  4394.     ^self bounds: bBox!
  4395.  
  4396. computeExtent
  4397.     "Fillers have a natural size of zero"
  4398.     ^self preferredExtent: self minimumExtent! !
  4399.  
  4400. !FillerInteractor methodsFor: 'rendering'!
  4401.  
  4402. obsoleteRenderOn: aGC
  4403.     "aGC
  4404.         paint: self backgroundColor;
  4405.         displayRectangle: self bounds"! !
  4406.  
  4407. !FillerInteractor methodsFor: 'printing'!
  4408.  
  4409. printHierarchyOn: aStream indent: i
  4410.  
  4411.     aStream crtab: i; nextPutAll: self class name , self auxiliaryPrintInfo! !
  4412.  
  4413. View subclass: #InteractorView
  4414.     instanceVariableNames: 'rootInteractor '
  4415.     classVariableNames: ''
  4416.     poolDictionaries: ''
  4417.     category: 'Interactors-Framework'!
  4418. InteractorView comment:
  4419. 'PixmapView is a scrollable view onto a Pixmap.
  4420.  
  4421. The view updates upon receipt of an update message; this usually has to be initiated by sending changed to the underlying Pixmap.'!
  4422.  
  4423.  
  4424. !InteractorView methodsFor: 'initialize-release'!
  4425.  
  4426. release
  4427.  
  4428.     rootInteractor release.
  4429.     rootInteractor := nil.
  4430.     super release! !
  4431.  
  4432. !InteractorView methodsFor: 'displaying'!
  4433.  
  4434. displayOn: aGC
  4435.     model displayOn: aGC! !
  4436.  
  4437. !InteractorView methodsFor: 'accessing'!
  4438.  
  4439. displayObject
  4440.     ^model!
  4441.  
  4442. interactor: root
  4443.     rootInteractor := root! !
  4444.  
  4445. !InteractorView methodsFor: 'controller accessing'!
  4446.  
  4447. defaultControllerClass
  4448.     ^InteractorController!
  4449.  
  4450. setController: aController
  4451.  
  4452.     super setController: aController! !
  4453.  
  4454. !InteractorView methodsFor: 'resizing'!
  4455.  
  4456. bounds: bBox
  4457.     model bounds = bBox
  4458.         ifFalse: [rootInteractor recomposeIn: bBox]! !
  4459.  
  4460. !InteractorView methodsFor: 'event processing'!
  4461.  
  4462. keyboardDown: aPoint
  4463.  
  4464.     ^rootInteractor keyboardDown: aPoint!
  4465.  
  4466. operateDown: aPoint
  4467.  
  4468.     ^rootInteractor operateDown: aPoint!
  4469.  
  4470. selectDown: aPoint
  4471.  
  4472.     ^rootInteractor selectDown: aPoint!
  4473.  
  4474. startUp: aPoint
  4475.  
  4476.     ^rootInteractor startUp: aPoint! !
  4477. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  4478.  
  4479. InteractorView class
  4480.     instanceVariableNames: ''!
  4481.  
  4482.  
  4483. !InteractorView class methodsFor: 'instance creation'!
  4484.  
  4485. model: aPixmap interactor: root
  4486.     "Answer an instance of the receiver whose model is aPixmap."
  4487.  
  4488.     | aView |
  4489.     aView := (self new) model: aPixmap; interactor: root.
  4490.     ^aView! !
  4491. VirtualInteractor initialize!
  4492.  
  4493. SliderInteractor initialize!
  4494.  
  4495. InsetInteractor initialize!
  4496.  
  4497. ActiveInteractor initialize!
  4498.  
  4499. BorderInteractor initialize!
  4500.  
  4501. GraphInteractor initialize!
  4502.  
  4503. CompositeInteractor initialize!
  4504.  
  4505.